越来越感觉学习python一个第三方库就跟学一门新语言差不多,庞大的TensorFlow更是如此。这篇博客会持续记录关于tensorflow的一些api的用法。
轴(axis)
在tensorflow中,最基本的变量或者常量都是tensor类型,说直接点就是多维数组,因此涉及到了很多在某一个维度上操作的API,比如tf.reduce_*()
,tf_arg*()
,tf_expand_dims()
等,这些基本的API都有一个共同的参数:axis=
,也就说这些操作都是哪些维度(轴)上做运算,除了在tf中,在numpy里面也有这一参数,之前一直是一知半解。现在总结一下这个axis,由于numpy与tensorflow的axis基本一样,因此下面以numpy为例。
首先可以从多维数组(tensor)的shape来得到数组的维度: d=len(array.shape)
:
1 | In [2]: a = np.array([[1,2,3],[4,5,6]]) |
也就是说上述的数组a的shape为(2,3)
,维度是2维,也就是有两层嵌套数组,看看有多少层[]
,因此axis
的取值只能为0,1
,下面以sum
为例,看看不同的axis的结果:
1 | In [5]: np.sum(a) |
一个一个的说明。首先需要明白操作的对象是谁?这这个例子中,就是那些元素相加。怎么来确定是哪些元素呢?个人使用的原则是:
对原来数组去掉axis+1层嵌套([]),对剩下的元素再分组进行相应的操作。
首先如果不加axis
参数,则默认对所有元素直接做sum
操作,因此结果就是21。当axis=0
的时候, 相加的对象,则是变成了[1,2,3]+[4,5,6]
,按照上面的原则,a去掉一层嵌套,也就是[]
之后,变为: [1,2,3],[4,5,6]
那么sum
的对象: [1,2,3]+[4,5,6]=[5,7,9]
。 再接着看axis=1
,这时候需要去掉两层嵌套,去掉第一层变为:[1,2,3], [4,5,6]
,去掉第二层嵌套,剩下了1,2,3
和 4,5,6
两个组,因此两个组内各个相加即可,得到的最终的结果为:[6,15]
。 下面以同样的思路,计算最小值:
1 | In [3]: np.min(a) |
有一个稍微特殊的是expand_dims
这个是扩展维度。对于这个api它的axis没有上限约束,不过当所有的元素自成一个列表之后,不再变化。它的axis
参数不一样的地方,是在axis
的位置加入新的一个轴,也就是说此时对原数组去掉axis
层嵌套,而非axis+1
层,然后再对每组进行加一个轴,看例子:
1 | In [25]: a |
到现在基本上tensorflow以及numpy的axis这个参数基本没有问题了。 下面再看几个常用的函数。
tf.slice
这个函数主要用于对多维数组的截取(切片),首先看看原型:
1 | tf.slice(input_, begin, size, name=None) |
- input_: 输入
- begin: 开始截取的位置
- size: 每一个维度截取的长度
直接看文档的例子:
1 | # 'input' is [[[1, 1, 1], [2, 2, 2]], |
先看第一个例子:
begin=[1,0,0]
也就是开始的元素,这里就是input[1][0][0] = 3
,就是第二行[3,3,3]
的第一个3,,再看截取距离: [1,1,3]
,首先在axis=0
的上截取一个距离,得到是第二整行[[3,3,3],[4,4,4]]
,在axis=1
上截取2个距离,得到[3,3,3]
,最后在axis=2
上截取了3个距离,也就是[3,3,3]
这三个元素都得到,最终结果为:[3,3,3]
。
第二个例子解析:
开始的元素仍然是input[1][0][0=0]
,在axis=0
上截取1个距离,得到仍然是[[[3,3,3],[4,4,4]]]
,第二个维度上截取距离为2,得到[[[3,3,3],[4,4,4]]]
,最后在第三个维度上截取3,即三个元素都保留,得到结果。这里如果第三个维度截取2的话,那么得到就是[[[3,3],[4,4]]]
。
第三个同理,不再叙述。
参考: 1
tf.nn.embedding_lookup
这个函数在涉及到词向量的NLP的一些task上非常常见,顾名思义,它的功能说白了就是查表。 首先看看基本原型(忽略一些参数):
1 | tf.nn.embedding_lookup(params, ids, name=None) |
首先params
是一个向量或者Tensor, 也就是我们的表。 比如我们使用word2vec训练出了1000个词的词向量,且维度为128, 存到了params
里面, 那么params
的维度就是(1000,128)
可以看成1000行128列的矩阵,这个矩阵就是我们要查的表.
ids
这个参数简单来说则是表示要从表中需要取出哪几行元素。 比如ids=[0,1,3]
表示从上述的params
中取出第0,1,3行的向量,这里是整行的取。
先看个简单的例子: 1
2
3
4>>a = tf.constant([[1,2,3],[4,5,6],[7,8,9]])
>>tf.nn.embedding_lookup(a, [0,2]).eval()
>>Out: array([[1, 2, 3],
[7, 8, 9]], dtype=int32)
上述例子中ids=[0,2]
表示取出第0行和第2行的内容,也就是[1,2,3]
和[7,8,9]
.
当然这个函数还可以更强大。 首先ids
可以查多次,并将多次的结果放到数组里:
1 | >>a = tf.constant([[1,2,3],[4,5,6],[7,8,9]]) |
其次,前面都是在说params
是二维向量,其实可是高维的Tensor,这样在查的时候,道理一样,结合上面的轴的概念,其实就是取第一层[]
里面的某几个元素.
最后举个常用的例子, 在文本分类任务中,如何表示句子呢?有个词汇表V,首先将每个句子用词袋模型表示,就是把每个句子表示成单词在词汇表下标的形式,以此作为ids
这个参数,params
就是前面训练好的词向量表,利用这个tf.nn.embedding_lookup
,就可以取出这个句子的词向量了。