main1.py文件
tf.no_op()
tf.tile()平铺之意,用于在同一维度上的复制。multiples参数维度与input维度应一致
tile(
input, #输入
multiples, #同一维度上复制的次数
name=None
)
tf.range()
tf.range(limit, delta=1, dtype=None, name='range')
tf.range(start, limit, delta=1, dtype=None, name='range')
#以start为起点,delta为变化量,生成不超过,且不包含limit的Tensor
model.py文件
- [√ ] 疑问1:key_masks = tf.expand_dims(tf.to_float(tf.not_equal(x, 0)),
-1)提前padding mask
答:避免泄露信息,行和列都做mask - [ √] 疑问2:queries=normalize(self.seq), #对输入做Layer Normalization?
疑问3:tf.layers.dropout(self.enc,rate=args.dropout_rate)#对输入做dropout?
疑问4:outputs = tf.layers.dropout(outputs,
rate=dropout_rate)#对attention做dropout?
答:不正规的操作,都是作者调优总结出来的 - [ √] 疑问5:outputs = normalize(outputs) = self.enc 重复做两次LN?
答:影响不大
skill id 应该从0还是1开始? id为0是否用来作padding_id
In [3]:tf.tile(tf.expand_dims(tf.range(5), 0), [3, 1])
Out[3]:
<tf.Tensor: shape=(3, 5), dtype=int32, numpy=
array([[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4],
[0, 1, 2, 3, 4]])>
In [4]:x = tf.constant([[1,2,3,0,0],[1,2,0,0,0]])
In [5]:x.shape
Out[5]: TensorShape([2, 5])
In [6]:key_masks = tf.expand_dims(tf.to_float(tf.not_equal(x, 0)), -1)
Traceback (most recent call last):
File "<ipython-input-6-c174d1bd98d4>", line 1, in <module>
key_masks = tf.expand_dims(tf.to_float(tf.not_equal(x, 0)), -1)
AttributeError: module 'tensorflow' has no attribute 'to_float'
In [7]:key_masks = tf.expand_dims(tf.cast(tf.not_equal(x, 0),dtype=tf.float32), -1)
In [8]:key_masks
Out[8]:
<tf.Tensor: shape=(2, 5, 1), dtype=float32, numpy=
array([[[1.],
[1.],
[1.],
[0.],
[0.]],
[[1.],
[1.],
[0.],
[0.],
[0.]]], dtype=float32)>
module.py文件
正则化方法tf.contrib.layers.l2_regularizer
tf.nn.moments()是用于计算均值和方差。
注意axes: 需要进行求均值/方差的维度。
如果shape为(2,3,3),axis=【0,1】,则以剩余的第三维作为对象。每个对象拥有shape为(2,3)的实体。
更详细参考
tensorflow2.+中 keep_dims=True 改为 keepdims=True
tf.Variable([[[1,3,2],[4,5,6],[7,8,9]],[[1,3,2],[4,5,6],[7,8,9]]], dtype=tf.float32)
mean, variance = tf.nn.moments(s, [-1])
In [13]:mean
Out[13]:
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[2., 5., 8.],
[2., 5., 8.]], dtype=float32)>
mean, variance = tf.nn.moments(s, [0,1])
In [15]: mean
Out[15]: <tf.Tensor: shape=(3,), dtype=float32, numpy=array([4. , 5.3333335, 5.6666665], dtype=float32)>
tf.linalg.LinearOperatorLowerTriangular
生成下三角矩阵,需要使用to_dense()函数生成实例矩阵。
tf.variable、tf.get_variable的区别见过最清晰的解释。
在一个模型需要使用其他模型的变量时,tf.get_variable就派上大用场了。
- tf.Varibale是以定义的变量名称为唯一标识的,所以可以重复地创建name='firstvar’的变量,由于tf.Varibale是以定义的变量名称为唯一标识的,所以当第二次命名同一个变量名时,第一个变量就会被覆盖。
- 对于tf.get_variable,它是以指定的name属性为唯一标识,而不是定义的变量名称,所以不能同时定义两个变量name是相同的
tf.layers.conv1d,pytorch好像维度方面要做调整
一维卷积 与 kernel为(1,1)的二维卷积是不一样的。
核心:1D卷积的kernel是针对timestep来移动的,1DPooling也是如此。
疑问6:1维卷积比全连接要多参数???
答:如果1维卷积的kernel size==1,则进行卷积的是1*dim的长条。参数其实和全连接是一样的。
tf2的代码
def conv(emb):
net = tf.keras.layers.Conv1D(10,1,use_bias=False,name="1Dconv")
out = net(emb)
print(net.weights)
print(out.shape)
def linear(emb):
net = tf.keras.layers.Dense(10,use_bias=False)
out = net(emb)
print(net.weights)
print(out.shape)
emb = tf.constant(0.8,shape=[2,4,5],dtype=tf.float32)
conv(emb)
linear(emb)
[<tf.Variable '1Dconv/kernel:0' shape=(1, 5, 10) dtype=float32, numpy=...
(2, 4, 10)
[<tf.Variable 'dense_1/kernel:0' shape=(5, 10) dtype=float32, numpy=...
(2, 4, 10)
如果你的kernel size==2,其实1维卷积参数是比全连接多的,但是outp size不一样。1维卷积会导致降维,即[batch,step,dim]中的step会减少。
实验结果
技能数为124,索引id从 1 ~ 124。 id=0,用来padding
我得到的结果为0.8092已经不错了,比预期,因为很多人都说复现不了论文的0.8483。而且还打不到0.80。(可能数据集的原因)
因为这是第一篇用Transformer做的,所以还是勇气可嘉,开了先河。接下来,我就要看更多关于Transformer模型应用于知识追踪任务了。