为什么共享图层后,输出向量的形状还不一样
# 这一层可以输入一个矩阵,并返回一个 64 维的向量
shared_lstm = LSTM(64)
# 当我们重用相同的图层实例多次,图层的权重也会被重用 (它其实就是同一层)
encoded_a = shared_lstm(tweet_a)
encoded_b = shared_lstm(tweet_b)
这里重用了shared_lstm 层,但是如果要我们获取输出形状时,有文章指出图层的权重是一样的,但是输出形状不一样,这里不太理解
assert shared_lstm.get_output_at(0) == encoded_a
assert shared_lstm.get_output_at(1) == encoded_b
虽然我们可以通过shared_lstm 的方法来获取图层,但是我不太理解,我的理解是输出已经定义好了,所有的输入的输出都是一样的,写个代码可以了解一下。
a = Input(shape=(280, 128))
b = Input(shape=(250, 128))
lstm = LSTM(32)
encoded_a = lstm(a)
encoded_b = lstm(b)
print(lstm.get_input_shape_at(0))
print(lstm.get_input_shape_at(1))
print(lstm.get_output_shape_at(0))
print(lstm.get_output_shape_at(1))
输出结果:
(None, 280, 128)
(None, 250, 128)
(None, 32)
(None, 32)
其中如果a、b的input中,shape的后一维向量不一样就会报错,根据矩阵运算来说,后一维矩阵关系到后一个向量的行维数,如果不同,则两次输入得到的向量维数都是不一样的,这是我的理解,也不知道对不对,
疑问:
- 1、如果两次调用通一个层,同一个输入维数,用的是也是两个层,那么权重怎么共享?
- 2、对这个共享还是不太理解,我觉得共享就是权重也是共享的,这个权重对于同一个维数的输入来说应该是一样的。
Embedding层和Input层有啥区别
这两个层都是作为网络模型的第一层,当然模型也可以不用这个层,所以我就很奇怪,这两个层作为第一层的作用是什么?他们之间有什么区别?
Input层 很多资料就说实例化一个keras张量,如下:
x = Input(shape=(32,))
明显很多layers的输出都是返回一个向量,
Embedding层:嵌入层将正整数(下标)转换为具有固定大小的向量,如[[4],[20]]->[[0.25,0.1],[0.6,-0.2]]
是不是很奇怪,这个怎么转换的?其实这里的embeding 是词向量化,但我不清楚 是不是用的word2vec,但大概是用的skip-word算法来构建的,将输入作为语料集,一定长度的窗口来滑动,训练模型从而得到指定长度的输出词的相似性,输出的是相关性较高的词的概率,一共有窗口大小的长度,
如果输入数据不需要词的语义特征语义,简单使用Embedding层就可以得到一个对应的词向量矩阵,但如果需要语义特征,我们大可把训练好的词向量权重直接扔到Embedding层中即可
大家可以看下这个定义:
keras.layers.Embedding(input_dim, output_dim, embeddings_initializer='uniform', embeddings_regularizer=None, activity_regularizer=None, embeddings_constraint=None, mask_zero=False, input_length=None)
- input_dim: int > 0。词汇表大小, 即最大整数 index + 1,类似语料集分词后词汇大小。
- output_dim: int >= 0。词向量的维度。
- input_length: 输入序列的长度,当它是固定的时。 如果你需要连接 Flatten 和 Dense 层,则这个参数是必须的 (没有它,dense 层的输出尺寸就无法计算)
model = Sequential()
model.add(Embedding(4, 5, input_length=7))
model.compile('rmsprop','mse')
model.predict(np.array([[0,1,0,1,1,0,3]]))
输出结果:
array([[[-0.03462106, 0.01587335, -0.04886673, 0.01961641,
0.01314208],
[ 0.02410911, -0.03580334, 0.02348015, 0.02070605,
0.01584761],
[-0.03462106, 0.01587335, -0.04886673, 0.01961641,
0.01314208],
[ 0.02410911, -0.03580334, 0.02348015, 0.02070605,
0.01584761],
[ 0.02410911, -0.03580334, 0.02348015, 0.02070605,
0.01584761],
[-0.03462106, 0.01587335, -0.04886673, 0.01961641,
0.01314208],
[ 0.00639332, -0.03460374, 0.01854259, 0.02507687,
0.03259133]]], dtype=float32)
参数分析:
- 4:3+1,一共有3个词汇,0、1、3
- 5:词向量的维度
- 7:输入的长度
具体可以看下参考博客。
dot()
全称是 tf.keras.backend.dot,表示两个矩阵相乘得到一个新的矩阵。
# dot product between tensors
>>> x = K.placeholder(shape=(2, 3))
>>> y = K.placeholder(shape=(3, 4))
>>> xy = K.dot(x, y)
>>> xy
<tf.Tensor 'MatMul_9:0' shape=(2, 4) dtype=float32>
不过这些都是只有形状,也就是说并不知道这个矩阵的具体值是多少,可能跟我们线性代数里的具体的矩阵不太一样,毕竟这里只是定义这么一个相乘的操作。
Model类与Layer的区别
这里的Layer包括我们自己定义的Layer Class。通常,我们使用Layer类来定义内部计算块,并使用Model类来定义外部模型 - 即要训练的对象。
Model类与Layer的区别:
它公开了内置的训练,评估和预测循环(model.fit(),model.evaluate(),model.predict())。
它通过model.layers属性公开其内层列表。
它公开了保存和序列化API。
参考博客
keras中文
keras:3Embedding层详解