Keras 中的 Masking 與 Padding
機(jī)器學(xué)習(xí)中的 Mask 與 Padding 是兩個(gè)經(jīng)常會(huì)使用到的概念,而之前我們也接觸到一部分,那就是在我們進(jìn)行文本分類的時(shí)候曾經(jīng)接觸過 Padding。而這節(jié)課我們就來詳細(xì)了解一下 Masking 與 Padding 的概念以及基本的用法。
1. 基本概念
雖然 Mask(遮掩)和 Padding(填充)這兩個(gè)概念看上去似乎很難理解,但是他他們的作用卻很簡(jiǎn)單。簡(jiǎn)單來說,Mask與Padding的作用分別是:
- Padding:將本來不相同的樣本填充到相同的長(zhǎng)度,以便于后面的處理,我們一般使用0做填充;
- Mask:告訴網(wǎng)絡(luò)層那些是真正的數(shù)據(jù),哪些是填充的“0”,從而幫助網(wǎng)絡(luò)層更好地計(jì)算。
簡(jiǎn)單舉例,下面是我們的三個(gè)文本:
[
['Hello', 'Hi'],
['Who', 'are', 'you'],
['what', 'time', 'is', 'it', 'now']
]
假設(shè)我們將其編碼之后得到的向量為:
[
[1, 2],
[3, 4, 5],
[6, 7, 8, 9, 10]
]
于是我們將這三個(gè)張量填充到共同長(zhǎng)度——5:
[
[1, 2, 0, 0, 0],
[3, 4, 5, 0, 0],
[6, 7, 8, 9, 10]
]
經(jīng)過填充之后我們得到了三個(gè)長(zhǎng)度相同的向量,于是我們可以計(jì)算出mask來告訴網(wǎng)絡(luò)哪些數(shù)據(jù)是填充的,哪些數(shù)據(jù)是真實(shí)的數(shù)據(jù)。于是我們得到了該向量的Mask:
[
[True, True, False, False, False],
[True, True, True, False, False],
[True, True, True, True, True ]
]
通過上面的例子相信大家可以清楚的了解到機(jī)器學(xué)習(xí)中Mask與Padding的概念。下面我們可以看一下在TesnorFlow之中如何使用這兩者吧。
2. TensorFlow 中的 Padding
在TensorFlow之中,我們最常使用的方法是采用預(yù)處理的方式進(jìn)行序列的Padding,就像我們?cè)谖谋痉诸愔兴龅哪菢印?/p>
下面是一個(gè)簡(jiǎn)單的示例:
import tensorflow as tf
inputs = [
[1, 2],
[3, 4, 5],
[6, 7, 8, 9, 10]
]
inputs = tf.keras.preprocessing.sequence.pad_sequences(
raw_inputs, padding="post", value=0
)
print(inputs)
于是我們可以得到輸出:
[[ 1 2 0 0 0]
[ 3 4 5 0 0]
[ 6 7 8 9 10]]
以上就是TensorFlow中進(jìn)行填充最常用的方法。
3. TensorFlow 中的 Mask
在TensorFlow之中使用Mask也是比較簡(jiǎn)單的,主要有兩種方法:
- 添加一個(gè)tf.keras.layers.Embedding層并設(shè)置參數(shù)mask_zero=True;
- 添加一個(gè)tf.keras.layers.Masking層。
這里我們使用之前的文本分類的模型作為例子來進(jìn)行演示。值得注意的是,在很多情況之下,如果我們不使用Mask,那么模型依然會(huì)繼續(xù)運(yùn)行,但是采用Mask會(huì)讓模型更加精確。
我們?cè)瓉淼木W(wǎng)絡(luò)為:
model = tf.keras.Sequential([
tf.keras.layers.Embedding(10000, 32),
tf.keras.layers.GlobalAveragePooling1D(),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.summary()
我們可以查看到模型的結(jié)構(gòu)為:
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) (None, None, 32) 320000
_________________________________________________________________
global_average_pooling1d (Gl (None, 32) 0
_________________________________________________________________
dense (Dense) (None, 64) 2112
_________________________________________________________________
dense_1 (Dense) (None, 1) 65
=================================================================
Total params: 322,177
Trainable params: 322,177
Non-trainable params: 0
_________________________________________________________________
1. 使用tf.keras.layers.Embedding層并設(shè)置mask_zero=True
因?yàn)槲覀円呀?jīng)使用了Embedding,因此我們只需要直接設(shè)置參數(shù)mask_zero=True即可:
model2 = tf.keras.Sequential([
tf.keras.layers.Embedding(10000, 32, mask_zero=True),
tf.keras.layers.GlobalAveragePooling1D(),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model2.summary()
于是我們可以看到網(wǎng)絡(luò)的結(jié)構(gòu):
Model: "sequential_2"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding_2 (Embedding) (None, None, 32) 320000
_________________________________________________________________
global_average_pooling1d_2 ( (None, 32) 0
_________________________________________________________________
dense_4 (Dense) (None, 64) 2112
_________________________________________________________________
dense_5 (Dense) (None, 1) 65
=================================================================
Total params: 322,177
Trainable params: 322,177
Non-trainable params: 0
_________________________________________________________________
我們可以發(fā)現(xiàn)網(wǎng)絡(luò)的結(jié)構(gòu)沒有發(fā)生變化,為了驗(yàn)證該Mask已經(jīng)生效,于是我們可以進(jìn)行測(cè)試:
print(model(inputs))
print(model2(inputs))
我們可以通過輸出看到,我們?cè)O(shè)置的遮掩(Mask)已經(jīng)生效:
tf.Tensor(
[[0.5014145 ]
[0.50220466]
[0.5058755 ]], shape=(3, 1), dtype=float32)
tf.Tensor(
[[0.4913409 ]
[0.49880138]
[0.49782944]], shape=(3, 1), dtype=float32)
2. 使用tf.keras.layers.Masking層
我們依然以我們的文本分類模型為例,為了添加Masking層,我們將模型進(jìn)行如下修改:
model3 = tf.keras.Sequential([
tf.keras.layers.Masking(input_shape=(256,)),
tf.keras.layers.Embedding(10000, 32),
tf.keras.layers.GlobalAveragePooling1D(),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model3.summary()
在該模型之中,因?yàn)镸asking層是位于第一層,因此我們要設(shè)置參數(shù)input_shape,這里的參數(shù)(256,)表示的是我們的每條數(shù)據(jù)都是padding長(zhǎng)度為256的序列。
于是我們可以得到輸出:
Model: "sequential_10"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
masking_5 (Masking) (None, 256) 0
_________________________________________________________________
embedding_10 (Embedding) (None, 256, 32) 320000
_________________________________________________________________
global_average_pooling1d_10 (None, 32) 0
_________________________________________________________________
dense_20 (Dense) (None, 64) 2112
_________________________________________________________________
dense_21 (Dense) (None, 1) 65
=================================================================
Total params: 322,177
Trainable params: 322,177
Non-trainable params: 0
_________________________________________________________________
由此可以看到,雖然masking層沒有參數(shù),但是它確實(shí)作為一個(gè)網(wǎng)絡(luò)層包含進(jìn)了網(wǎng)絡(luò)。
3. 小結(jié)
在這節(jié)課之中,我們學(xué)習(xí)了如何進(jìn)行Padding,也學(xué)習(xí)到了如何設(shè)置Mask。這兩種操作互相結(jié)合可以使得我們的處理序列的模型的精確度和準(zhǔn)確率有很大的提升。