文章目錄
對列表生成式和dict生成式的使用
imdb = keras.datasets.imdb
word_index = imdb.get_word_index()
word_index = {k:(v+3) for k,v in word_index.items()}
reverse_word_index = {v:k for k,v in word_index.items()}
pad_sequences
train_data = keras.preprocessing.pad_sequences(
train_data, # 待填充數據
value=0, # 用0填充
padding='post', # 在後面填充
maxlen=max_length
)
train_data應該是list<list<number>>類型的數據,不等長數組組成的數組
Embedding層
keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length)
相當於對one-hot變量降維。輸入層本來是batch_size×maxlen的數據,寫成batch_size×maxlen×vocab_size的獨熱形式,再降維到batch_size×maxlen×embedding_dim。
GlobalAveragePooling
keras.layers.GlobalAveragePooling1D()
在最後一個維度上取平均。得到batch_size×embedding_dim
SimpleRNN
single_rnn_model = keras.models.Sequential([
keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
keras.layers.SimpleRNN(units=64, return_sequences=False),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dense(1, activation='sigmoid')
])
Emebedding返回的是batch_size×embedding_dim×maxlen大小的矩陣,SimpleRNN裏面有64個節點,
embedding_dim這個維度和64個節點連接,就像全連接層中embedding_dim個節點和64個節點連接一樣。maxlen這個維度的每個元素逐個輸入進RNN中,並且只保留最後一次的結果,維度會變成1。所以最終維度變成batch_size×64×1。
雙向RNN
model = keras.models.Sequential([
keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
keras.layers.Bidirectional(
keras.layers.SimpleRNN(units=32, return_sequences=True)),
keras.layers.Bidirectional(
keras.layers.SimpleRNN(units=32, return_sequences=False)),
...
])
雙向RNN。好像會創建兩層RNN,兩層RNN都向外輸出。
return_sequences=True會把maxlen這個維度上的每次的結果都保存下來,
所以第一個Bidrectional的輸出大小是batch_size×maxlen×64,第二個輸出大小是batch_size×64
tf.random.categorical
# in
tf.random.categorical(tf.math.log([[0.1, 0.9], [0.2, 0.8], [0.3, 0.7]]), 20)
# out
<tf.Tensor: id=53, shape=(3, 20), dtype=int64, numpy=
array([[1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1],
[0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0]],
dtype=int64)>
參數 logits——對數概率分佈,num_samples——抽樣次數
從len(logits)個概率分佈中隨機抽樣num_samples次。比如上面是從3個分佈中抽樣20次。
保存與載入模型
output_dir = './text_generation_checkpoints'
if not os.path.exists(output_dir): os.mkdir(output_dir)
checkpoint_prefix = os.path.join(output_dir, "ckpt_{epoch}")
checkpoint_callback = keras.callbacks.ModelCheckpoint(
filepath=checkpoint_prefix,
save_weights_only=True # 只保存參數的值(不保存模型)
)
epochs = 100
history = model.fit(seq_dataset, epochs=epochs, callbacks=[checkpoint_callback])
保存checkpoint, 可以直接把{epoch}包含在字符串內,weights是參數的值。
model2 = keras.models.Sequential ...
model2.load_weights(tf.train.latest_checkpoint(output_dir)) # 載入參數值
model2.build(tf.TensorShape([1, None])) # None 是變長序列, 需要重新定義模型的輸入
之前用的是tf.keras.models.Model.compile, 在load模型時需要用build載入tf.keras.layers.Layer.build(input_shape)。
expand_dims 和 squeeze
input_eval = tf.expand_dims(input_eval, axis=0) # 爲 tensor 添加一個維度1
predictions = tf.squeeze(input_eval, 0) # 去掉第dim=1的0個維度
把input_eval由n維變成1×n維,在變回n維
LSTM
用法跟SimpleRNN一樣
model = keras.models.Sequential([
keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
keras.layers.Bidirectional(keras.layers.LSTM(units=32, return_sequences=True)),
keras.layers.Bidirectional(keras.layers.LSTM(units=32, return_sequences=False)),
keras.layers.Dense(64, activation='relu'),
keras.layers.Dense(1, activation='sigmoid')
])