文章目录
concat & concatenate & add
一般情况下tf.concat和tf.keras.layers.concatenate是通用的
1、当数据为np.array时,推荐使用tf.concat
t1 = np.array([[1, 2, 3], [4, 5, 6]])
t2 = np.array([[7, 8, 9], [10, 11, 12]])
(1)按列拼接
tf.concat([t1, t2], axis = 1)
#或者
tf.keras.layers.Concatenate(axis=1)([t1, t2])
(2)按列拼接
tf.concat([t1, t2], axis=1)
# 或者
tf.keras.layers.Concatenate(axis=0)([t1, t2])
2、当数据为网络层输出结果时,推荐使用tf.keras.layers.Concatenate
x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2)) # shape=(5,8)
x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2)) # shape=(5,8)
# 方法一:推荐使用
concatted = tf.keras.layers.Concatenate()([x1, x2])
print(concatted.shape)
# 方法二
tf.concat([x1,x2],1)
# 结果:shape=(5,16)
3、 Add用于层之间的加法运算,即 y = x1+ x2
input_shape = (2, 3, 4)
x1 = tf.random.normal(input_shape)
x2 = tf.random.normal(input_shape)
x2
y = tf.keras.layers.add([x1, x2])
x1,x2,y
Flatten & Embedding
1、Flatten 展开神经网络的计算结果,具体示例如下:
model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(64, 3, 3, input_shape=(3, 32, 32)))
model.output_shape
# (None, 1, 10, 64)
# 执行展开操作:
model.add(Flatten())
model.output_shape
#(None, 640)
2、Embedding
该层可以仅被用作在一个模型中的第一层。具体用法如下:
tf.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, **kwargs
)
输入形状:(batch_size, input_length)
输出形状:(batch_size, input_length, output_dim)
参数说明:
参数 | 说明 |
---|---|
input_dim | 最大整数索引+ 1的大小。(如词库的个数) |
output_dim | 嵌入的尺寸 |
input_length | 输入序列的长度,当它是恒定的 |
embeddings_initializer | 初始化器的embeddings 矩阵(见keras.initializers )。 |
embeddings_regularizer | 正则函数施加到所述embeddings 矩阵(参见keras.regularizers )。 |
embeddings_constraint | 约束函数施加到所述embeddings 矩阵(参见keras.constraints )。 |
例子:该模型将输入一个大小为(batch_size,input_length),并且输入中的最大整数(即单词索引)应不大于input_dim=999(词汇量)。现在model.output_shape是(None,10,64),其中None
是批处理尺寸。
model = tf.keras.Sequential()
model.add(tf.keras.layers.Embedding(input_dim=1000, output_dim=64, input_length=10))
input_array = np.random.randint(1000, size=(32, 10))
model.compile('rmsprop', 'mse')
# 只有单独的Embedding层,不需要fit训练
output_array = model.predict(input_array)
print(output_array.shape)
乘法
tf.multiply(x,y)
tensor 对应位置相乘
x = tf.constant(([1, 2, 3, 4]))
tf.math.multiply(x, x)
# <tf.Tensor: id=8, shape=(4,), dtype=int32, numpy=array([ 1, 4, 9, 16])>
当x,y维度不同时,将使用广播机制进行计算
x = tf.ones([1, 2]);
y = tf.ones([2, 1]);
x * y # Taking advantage of operator overriding
# <tf.Tensor: id=6, shape=(2, 2), dtype=float32, numpy=
# array([[1., 1.],
# [1., 1.]], dtype=float32)>
tf.tensordot(a,b,axes)
这个函数接收三个参数,前两个就是numpy中数组,最后一个参数则是用于指定收缩的轴。可以让两个不同维度的数组进行相乘。
(1)axes = m,m为一个整数,表示指定数组a的后n个轴和数组b的前n个轴分别进行内积,就是对应位置元素相乘、再整体求和。
import numpy as np
a = np.arange(60).reshape((3, 4, 5))
b = np.arange(160).reshape((4, 5, 8))
print(np.tensordot(a, b, 2).shape) # (3, 8)
相当于以下两个矩阵相乘
a[1,:,:],b[:,:,1]
(2)axes为列表,[m, n],那么表示让a的第m+1个(索引为m)
轴和b的第n+1(索引为n)
个轴进行内积。使用列表的方法最大的好处就是,可以指定任意位置的轴。
import numpy as np
a = np.arange(60).reshape((3, 4, 5))
b = np.arange(160).reshape((4, 5, 8))
# 我们看到a的第二个维度(或者说轴)和b的第一个维度都是4,所以它们是可以进行内积的
c1 = np.tensordot(a, b, [1, 0])
# 由于内积的结果是一个标量,所以(3, 4, 5)和(4, 5, 8)在tensordot之后的shape是(3, 5, 5, 8)
# 相当于把各自的4给扔掉了(因为变成了标量),然后组合在一起
print(c1.shape) # (3, 5, 5, 8)
# 同理a的最后一个维度和b的第二个维度也是可以内积的
# 最后一个维度也可以使用-1,等于按照列表的索引来取对应的维度
c2 = np.tensordot(a, b, [-1, 1])
print(c2.shape) # (3, 4, 4, 8)
更多细节参考:numpy中的tensordot
tf.matmul
矩阵a乘以矩阵b,生成a * b
tf.matmul(a, b, transpose_a=False, transpose_b=False, adjoint_a=False, adjoint_b=False, a_is_sparse=False, b_is_sparse=False, name=None)
其他
https://blog.csdn.net/xinjieyuan/article/details/95760679
tf.sequence_mask()
# 函数定义
sequence_mask(
lengths,
maxlen=None,
dtype=tf.bool,
name=None
)
# 返回数据
return mask类型数据
- 函数返回的一个
mask
张量,默认其中内部元素类型是tf.bool
(布尔变量),只有True和 False 格式,也可以通过参数dtype
指定其他数据格式。一般实际代码中选择数据类型为tf.float32
,这样True
会变成1.,同理False
变成0。 - 参数
lengths
:是长度;可以是标量,也可以是列表 [ ] ,也可以是二维列表[ [ ],[ ] ,…],甚至是多维列表…。一般列表类型的用的比较多 - 参数
maxlen
:当默认None
,默认从lengths
中获取最大的那个数字,决定返回mask
张量的长度;当为N时,返回的是N长度。
举例1:当参数lenghts是标量
import tensorflow as tf
lenght = 4
mask_data = tf.sequence_mask(lengths=lenght)
# 输出结果,输出结果是长度为4的array,前四个True
array([ True, True, True, True])
# 定义maxlen时
mask_data = tf.sequence_mask(lengths=lenght,maxlen=6)
# 输出结果,输出结果是长度为6的array,前四个True
array([ True, True, True, True, False, False])
# 定义dtype时
mask_data = tf.sequence_mask(lengths=lenght,maxlen=6,dtype=tf.float32)
# 输出结果,输出结果是长度为6的array,前四个1.0
array([1., 1., 1., 1., 0., 0.], dtype=float32)
举例2:当参数lenghts是[ list ],这个形式的非常常用,主要是针对数据填充用的非常多。比如我一个batch_data
有10个数据,每个数据是一个句子,每个句子不可能是一样长的,肯定有短的需要填充0元素,那么lengths
就专门记录每个句子的长度的。
# 比如这个lenght就是记录了第一个句子2个单词,第二个句子2个单词,第三个句子4个单词
lenght = [2,2,4]
mask_data = tf.sequence_mask(lengths=lenght)
# 长度为max(lenght)
array([[ True, True, False, False],
[ True, True, False, False],
[ True, True, True, True]])
# 定义maxlen时
mask_data = tf.sequence_mask(lengths=lenght,maxlen=6)
# 长度为maxlen
array([[ True, True, False, False, False, False],
[ True, True, False, False, False, False],
[ True, True, True, True, False, False]])
# 定义dtype时
mask_data = tf.sequence_mask(lengths=lenght,maxlen=6,dtype=tf.float32)
# 长度为maxlen,数据格式为float32
array([[1., 1., 0., 0., 0., 0.],
[1., 1., 0., 0., 0., 0.],
[1., 1., 1., 1., 0., 0.]], dtype=float32)
tf.split()
对tensorflow 进行切分
tf.split(
value, num_or_size_splits, axis=0, num=None, name='split'
)
-
value: 被切割的tensor
-
num_or_size_splits
是指切分的大小。(1) 如果
num_or_size_splits
是一个整数,value
将被按照axis
被切割成num_or_size_splits
个小tensor. 注意这个过程要求value.shape[axis]
可以被num_or_size_splits
整除。
x = tf.Variable(tf.random.uniform([5, 30], -1, 1))
# Split `x` into 3 tensors along dimension 1
s0, s1, s2 = tf.split(x, num_or_size_splits=3, axis=1)
# 将x按照第一个维度进行切分成3份,所以每份大小为30/5=6
#s0.shape: shape=(5, 10)
(2)如果num_or_size_splits
是一个1-D Tensor (或者list), 将沿着指定的axis 按照 num_or_size_splits[i]的大小进行切分。
# Split `x` into 3 tensors with sizes [4, 15, 11] along dimension 1
split0, split1, split2 = tf.split(x, [4, 15, 11], 1)
tf.shape(split0).numpy()
# array([ 5, 4])
tf.shape(split1).numpy()
# array([ 5, 15])
tf.shape(split2).numpy()
# array([ 5, 11])
(3)以下代码按照列对矩阵进行切分,返回矩阵的每一列,并存在list中
x = tf.Variable(tf.random.uniform([5, 30], -1, 1))
x_cols = tf.split(x,30,axis=-1)
tf.tile
对tensor进行复制
tf.tile(
input, multiples, name=None
)
此操作通过多次复制输入来创建新的张量。输出张量的第i个维度具有input.dims(i)* multiples [i]
元素,并且输入值沿第i个维度重复了multi [i]次。例如,将[a b c d]乘以[2]会产生[a b c d a b c d]。
a = tf.constant([[1,2,3],[4,5,6]], tf.int32)
b = tf.constant([1,2], tf.int32)
# 表示将a的第一个维度复制1次,第2个维度复制两次
tf.tile(a, b)
# <tf.Tensor: id=306, shape=(2, 6), dtype=int32, numpy=
# array([[1, 2, 3, 1, 2, 3],
# [4, 5, 6, 4, 5, 6]])>
c = tf.constant([2,1], tf.int32)
# 表示将a的第一个维度复制2次,第2个维度复制1次
tf.tile(a, c)
# <tf.Tensor: id=308, shape=(4, 3), dtype=int32, numpy=
# array([[1, 2, 3],
# [4, 5, 6],
# [1, 2, 3],
# [4, 5, 6]])>
d = tf.constant([2,2], tf.int32)
# 表示将a的第一个维度复制2次,第2个维度复制2次
tf.tile(a, d)
# <tf.Tensor: id=310, shape=(4, 6), dtype=int32, numpy=
# array([[1, 2, 3, 1, 2, 3],
# [4, 5, 6, 4, 5, 6],
# [1, 2, 3, 1, 2, 3],
# [4, 5, 6, 4, 5, 6]])>
tf.gather & tf.slice()
tf.slice(input_, begin, size, name=None):按照指定的下标范围抽取连续区域的子集
tf.gather(params, indices, validate_indices=None,axis=None, name=None):按照指定的下标集合从axis=0中抽取子集,适合抽取不连续区域的子集
耐心的看懂下面的例子:
输出:
input = [[[1, 1, 1], [2, 2, 2]],
[[3, 3, 3], [4, 4, 4]],
[[5, 5, 5], [6, 6, 6]]]
# 假设我们要从input中抽取[[[3, 3, 3]]],这个输出在input中axis=0的下标是1,
# axis=1的下标是0,axis=2的下标是0-2,所以begin=[1,0,0],size=[1,1,3]。
tf.slice(input, [1, 0, 0], [1, 1, 3]) ==> [[[3, 3, 3]]]
# 假设我们要从input中抽取[[[3, 3, 3], [4, 4, 4]]],这个输出在inputaxis=0的下标是1,
# axis=1的下标是0-1,axis=2的下标是0-2,所以begin=[1,0,0],size=[1,2,3]。
tf.slice(input, [1, 0, 0], [1, 2, 3]) ==> [[[3, 3, 3],
[4, 4, 4]]]
# 假设我们要从input中抽取[[[3, 3, 3], [5, 5, 5]]],这个输出在inputaxis=0的下标是1-2,
# axis=1的下标是0,axis=2的下标是0-2,所以begin=[1,0,0],size=[2,1,3]。
tf.slice(input, [1, 0, 0], [2, 1, 3]) ==> [[[3, 3, 3]],
[[5, 5, 5]]]
# 假设我们要从input中抽取[[[1, 1, 1], [2, 2, 2]],[[5, 5, 5], [6, 6, 6]]],
# 这个输出在input的axis=0的下标是[0, 2],不连续,可以用tf.gather抽取。input[0]和input[2]
tf.gather(input, [0, 2]) ==> [[[1, 1, 1], [2, 2, 2]],
[[5, 5, 5], [6, 6, 6]]]
tf.expand_dims & tf.squeeze
例子:
# 't' is a tensor of shape [1, 2, 1, 3, 1, 1]
tf.shape(tf.squeeze(t)) # [2, 3]
# 't' is a tensor of shape [1, 2, 1, 3, 1, 1]
tf.shape(tf.squeeze(t, [2, 4])) # [1, 2, 3, 1]
tf.where()
tf.where(
condition, x=None, y=None, name=None
)
直接看例子:
(1)参数只有condition的情况: 返回True的坐标,并将其存入array中
tf.where([True, False, False, True])
# <tf.Tensor: id=440, shape=(2, 1), dtype=int64, numpy=
# array([[0],
# [3]], dtype=int64)>
tf.where([[[True, False], [False, True], [True, True]]])
<tf.Tensor: id=442, shape=(4, 3), dtype=int64, numpy=
# array([[0, 0, 0],
# [0, 1, 1],
# [0, 2, 0],
# [0, 2, 1]], dtype=int64)>
(2)参数有condition,x ,y 的情况
condition, x, y 相同维度,condition是bool型值,True/False
返回值是对应元素,condition中元素为True的元素替换为x中的元素,为False的元素替换为y中对应元素,x只负责对应替换True的元素,y只负责对应替换False的元素,x,y各有分工
由于是替换,返回值的维度,和condition,x , y都是相等的。
注:当x,y 维度不同,则使用广播机制进行填充
tf.where([True, False, False, True], [1,2,3,4], [100,200,300,400])
# <tf.Tensor: id=446, shape=(4,), dtype=int32, numpy=array([ 1, 200, 300, 4])>
# 以下例子均使用广播机制
tf.where([True, False, False, True], [1,2,3,4], [100])
# <tf.Tensor: id=450, shape=(4,), dtype=int32, numpy=array([ 1, 100, 100, 4])>
tf.where([True, False, False, True], [1,2,3,4], 100)
# <tf.Tensor: id=454, shape=(4,), dtype=int32, numpy=array([ 1, 100, 100, 4])>
tf.where([True, False, False, True], 1, 100)
# <tf.Tensor: id=458, shape=(4,), dtype=int32, numpy=array([ 1, 100, 100, 1])>
tf.cast()
tensorflow 更换数据类型
outputs = tf.cast(outputs,dtype=tf.float32)