Lecture 032. 图像先生成,目标句子只进入损失 · 实现代码
2. 图像先生成,目标句子只进入损失 · 实现代码
按问题继续
真实CNN–GRU条件训练与greedy/beam生成、遮图/错图消融
展开完整实现代码
def render_object(color, shape, position, rng):
canvas = Image.new('RGB', (32,32), (244,242,236))
painter = ImageDraw.Draw(canvas)
cx = {'left':8, 'center':16, 'right':24}[position] + int(rng.integers(-1,2))
cy = 16 + int(rng.integers(-4,5)); radius = int(rng.integers(4,7))
box = (cx-radius, cy-radius, cx+radius, cy+radius)
if shape == 'square': painter.rectangle(box, fill=COLORS[color])
else: painter.ellipse(box, fill=COLORS[color])
arr = np.array(canvas).astype(np.float32) / 255
arr = np.clip(arr + rng.normal(0,.018,arr.shape),0,1).astype(np.float32)
return arr
def make_caption_data(n, seed):
rng = np.random.default_rng(seed); images=[]; sequences=[]; descriptions=[]
conditions = [(c,s,p) for c in COLORS for s in ['square','circle'] for p in ['left','center','right']]
for i in range(n):
color, shape, pos = conditions[i % len(conditions)]
words = ['a',color,shape] + ([] if pos=='center' else ['on',pos])
sequence = [BOS] + [W[w] for w in words] + [EOS]
sequences.append(sequence+[PAD]*(7-len(sequence)))
images.append(render_object(color,shape,pos,rng)); descriptions.append(' '.join(words))
return torch.tensor(np.stack(images)).permute(0,3,1,2), torch.tensor(sequences), descriptions
Xtrain, Ytrain, train_text = make_caption_data(720,13031)
Xtest, Ytest, test_text = make_caption_data(180,13033)
# Independent random pixels/geometry; no duplicate image crosses the split.
train_hashes = {hashlib.sha256(x.numpy().tobytes()).hexdigest() for x in Xtrain}
assert not train_hashes.intersection(hashlib.sha256(x.numpy().tobytes()).hexdigest() for x in Xtest)
np.savez_compressed(OUT/'lab13-data.npz', train_images=Xtrain.numpy(), train_tokens=Ytrain.numpy(), test_images=Xtest.numpy(), test_tokens=Ytest.numpy())
print('images:', tuple(Xtrain.shape), tuple(Xtest.shape), 'tokens:', tuple(Ytrain.shape))
print('teacher input:', Ytrain[:3,:-1].tolist())
print('shifted target:',Ytrain[:3,1:].tolist())
print('loss mask:',Ytrain[:3,1:].ne(PAD).int().tolist())