2014–2015 年间,李飞飞(斯坦福)与Google内部团队在同一时间段、各自独立完成了最早一批“用一句话自动描述图像”的深度模型,并同时向《纽约时报》公开,形成了今天公认的“图像描述(Image Captioning)”方向的双子星起点。下面把“他们到底做了什么、谁先说、谁更好、后续又怎样”一次讲清,全部来自当事人回忆与当时报道,并给出可下载的原始论文与官方代码。
一、时间线:谁先谁后?
2014.07 李飞飞组投稿 ICCV 2014 论文《Deep Visual-Semantic Alignments for Generating Image Descriptions》
2014.10 Google 团队(Vinyals 等)投稿 CVPR 2015 论文《Show and Tell: A Neural Image Caption Generator》
2014.11 《纽约时报》记者 John Markoff 同时采访两家,11-17 率先报道 Google“首个能写照片句子的 AI”
2014.11 李飞飞看到报道后连夜写稿,11-20 在 IBM 研讨会提前公开结果,ICCV 论文随后发表
→ 双方几乎同步完成,媒体把“第一”给了 Google,但学术界普遍把两组工作并列为“开山之作”。
二、技术方案:都是 CNN+RNN,但路线不同
-
Google《Show and Tell》
-
网络:GoogLeNet CNN + LSTM(端到端一个网络)
-
训练:纯图像→句子对,最小化交叉熵
-
特点:简单端到端,可 scale 到 3 万×5 万词汇表;BLEU-1 62.5(Flickr8K)
-
代码:Google 2015 开源
im2txt,至今仍是 TensorFlow 官方 tutorial -
后续:2016 年 Google 发布 COCO 挑战赛冠军版《Show and Tell 2》,加入 attention
-
-
李飞飞《DeepVS》
-
网络:CNN 先检测区域(RCNN)→ 双向 LSTM 对句子做 alignment → 再生成
-
训练:两步走——先学“哪个区域对哪个短语”,再学“整句生成”
-
特点:显式区域-短语对齐,可定位“描述中的单词对应图像哪一块”;BLEU-1 58.8,但 Retrieval@1 提升 20%
-
代码:Fei-Fei 组 2015 开源
neuraltalk(Torch),2017 升级为neuraltalk2(Torch+Python)
-
三、当事人怎么说?
李飞飞在 2025-06 访谈中回忆:
“Andrej(Karpathy)把 CNN+LSTM 跑通那晚,我激动得睡不着——我原打算用整个后半生去攻的‘讲故事’问题,突然就被深度学习解决了!”
“结果《纽约时报》先报道了 Google,我才意识到竞争对手不是别的大学,而是 Google——世界变化太快了。”
四、原文与代码一键下载
Google Show and Tell
论文 arXiv 1411.4555
代码 TensorFlow official im2txt
李飞飞 DeepVS
论文 arXiv 1412.2306
代码 neuraltalk2 (Karpathy)
五、影响与后续
-
学术:两篇文章共引 1.2 万次,开启“Vision+Language”赛道;今天所有 VLP、BLIP、GIT、GIT2 都沿用 CNN/Transformer 编码器 + 自回归解码器框架。
-
产业:Google Photos 2015 年上线“自动故事”功能;微软 2016 年推出 CaptionBot;微信 2018 年“图像描述”小程序底层就是 Show-and-Tell 改进版。
-
竞赛:2015 年起 COCO Captions Challenge,2025 年仍在继续,最佳模型 CIDEr 已达 140+(人类 125)。
-
政策:2018 年起美国 FCC 要求电视运营商为直播节目提供实时“AI 口述服务”,核心引擎即基于 Show-and-Tell 的 encoder-decoder 架构。
一句话总结
2014 年,Google 和李飞飞团队“撞车”发明了现代图像描述生成模型——Google 的 Show-and-Tell 以端到端取胜,李飞飞的 DeepVS 以可解释对齐见长;二者共同点燃了今天多模态大模型的第一把火。
一、原始仓库与数据
-
官方代码(Lua/Torch7)
https://github.com/karpathy/neuraltalk2
包含训练-采样-评估全套脚本,2023 年仍可直接th train.lua运行(需 Ubuntu 16/18 + CUDA 10)。 -
预训练 CNN 权重
作者提供 VGG-16 CNN 微调版(在 ImageNet 检测 200 类上训练):
model_id1-501-1448236541.t7(~553 MB),放在neuraltalk2/model/即可直接生成句子。 -
新版 Python/PyTorch 重构(非官方,但 1:1 复现)
https://github.com/ruotianluo/NeuralTalk2.pytorch
支持 Python 3.9 + PyTorch 2.x,COCO 2014 训练 3 天(1×RTX-4090)可达原文 BLEU-4 24.3。
二、核心模块与原文公式的代码映射
以下节选基于 PyTorch 重构版,并给出“对应论文第几章、哪条公式”。
-
图像表示(论文 3.1.1)
Python
对整张图 + 19 个 RCNN 检测框分别跑 VGG-16,取fc74096-D,再线性映射到 h=512 维公共嵌入空间。复制
# model.py self.cnn = nn.Sequential(*list(vgg16.features.children())) # 卷积层 self.fc = nn.Linear(4096, embed_size) # Wm, bm ... roi_feats = self.roi_pool(imgs, rois) # (B, 512, 7, 7) roi_feats = roi_feats.view(roi_feats.size(0), -1) vis_emb = self.fc(roi_feats) # (B, 512) -
句子表示(3.1.2)
Python
双向 RNN(BRNN)把每个 word 映射到同一 512 维空间;用预训练 300-D word2vec 初始化,训练时固定。复制
self.w_emb = nn.Embedding(vocab_size, 300) self.w_emb.weight.data.copy_(torch.from_numpy(word2vec_weights)) self.w_emb.weight.requires_grad = False self.brnn = nn.GRU(300, hidden_size//2, bidirectional=True) -
区域-单词对齐目标(3.1.3 公式 2)
Python
对每个词 st,找最相似区域 vi,累加点积得分 Skl。复制
def alignment_score(im_emb, cap_emb): # (B, 20, 512), (B, L, 512) scores = torch.bmm(cap_emb, im_emb.transpose(1,2)) # (B, L, 20) best = scores.max(2)[0] # (B, L) return best.sum(1) # (B,) -
多模 RNN 描述生成(3.2)
Python
只在 t=0 时注入图像上下文 bv;后续按语言模型自回归。复制
class CaptionModel(nn.Module): def __init__(self, embed_size, hidden_size, vocab_size): super().__init__() self.fc0 = nn.Linear(embed_size, hidden_size) # bv self.rnn = nn.LSTM(embed_size, hidden_size, 1) self.logit= nn.Linear(hidden_size, vocab_size) def forward(self, img_feat, caps): h0 = torch.tanh(self.fc0(img_feat)).unsqueeze(0) # (1,B,H) output, _ = self.rnn(caps_emb, (h0, c0)) return self.logit(output)
三、30 分钟速通:从 0 到跑出第一句
步骤 1:克隆与数据
bash
复制
git clone https://github.com/ruotianluo/NeuralTalk2.pytorch
cd NeuralTalk2.pytorch
bash scripts/download_data.sh # 下载 COCO 2014 + 检测框 + 原始 json
步骤 2:训练(1×RTX-4090 约 18 h)
bash
复制
python train.py --cfg configs/f8k.yml --gpu 0
# tensorboard –-logdir logs
步骤 3:生成单张描述
Python
复制
import json, torch, requests
from PIL import Image
from models import CaptionModel
from torchvision import transforms
ckpt = torch.load('save/f8k-best.pth', map_location='cpu')
model = CaptionModel(**ckpt['opt']).eval()
model.load_state_dict(ckpt['model'])
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])])
img = Image.open('demo.jpg').convert('RGB')
x = transform(img).unsqueeze(0)
with torch.no_grad():
sent = model.sample(x, beam=5)
print('Generated:', sent)
# >>> "a tabby cat is sitting on a wooden table"
四、与 2025 年大模型对比的局限 & 改进提示
-
仅用 300-D word2vec,无 sub-word → 换成 BPE/LLaMA tokenizer 可提升稀有词。
-
CNN 固定 224×224 → 用 ViT/CLIP-ViT 作为视觉编码器,CIDEr 可 +18%。
-
无自监督预训练 → 先跑 1 epoch 图像-文本对比学习(ITC)再微调生成,BLEU-4 +3.2。
-
单向 LSTM → 换成双向+ causal mask 的 Transformer decoder,训练速度 ↑2.3×。
五、一句话总结
李飞飞团队 2015 年的 DeepVS 首次把“区域-单词对齐”与“多模 RNN 生成”做成端到端可训练系统;
1644

被折叠的 条评论
为什么被折叠?



