#将特征按照最后一个维度进行拼接
def concat_fun(inputs, axis=-1):
if len(inputs) == 1:
return inputs[0]
else:
# return tf.keras.layers.Concatenate(axis=axis)(inputs)
return tf.concat(inputs, axis=axis)
eg:a=[a1,a2,a3],其中a1,a2,a3的维度均是(None,1,32),执行b=concat_fun(a,axis=1),则b的维度为(None,3,32);执行c=concat_fun(a,axis=-1),则b的维度为(None,1,96);
#embdding特征和dense特征进行拼接
def combined_dnn_input(sparse_embedding_list, dense_value_list):
if len(sparse_embedding_list) > 0 and len(dense_value_list) > 0:
sparse_dnn_input = tf.keras.layers.Flatten()(concat_fun(sparse_embedding_list))
dense_dnn_input = tf.keras.layers.Flatten()(concat_fun(dense_value_list))
return concat_fun([sparse_dnn_input, dense_dnn_input])
elif len(sparse_embedding_list) > 0:
return tf.keras.layers.Flatten()(concat_fun(sparse_embedding_list))
elif len(dense_value_list) > 0:
return tf.keras.layers.Flatten()(concat_fun(dense_value_list))
else:
raise NotImplementedError
eg:a为稀疏特征列表,a=[a1,a2,a3],其中a1,a2,a3的维度均是(None,1,32);b为dense特征列表,b=[b1,b2,b3],其中b1,b2,b3的维度均是(None,1)
tf.keras.layers.Flatten()(a),Flatten层用来将输入“压平”,即把多维的输入一维化。Flatten不影响batch的大小。输入输出shape: 具体而言,是将一个维度大于或等于3的高维矩阵,“压扁”为一个二维矩阵。即保留第一个维度(如:batch的个数),然后将剩下维度的值相乘为“压扁”矩阵的第二个维度。如输入是(None,32,32,3),则输出是(None,3072)
在TensorFlow中,tf.split
函数是用来将一个张量(tensor)切分成多个张量的。这个操作可以让你沿着某个维度将一个大的张量切分成多个小的张量,返回一个张量list。
tf.split
的基本语法如下:
tf.split(value, num_or_size_splits, axis=0)
参数解释:
value
:待切分的输入张量。num_or_size_splits
:切分的方式。如果是单个整数,那么它代表要将张量切分成几个相等的小张量;如果是一个整数列表,那么列表中的每个元素表示每个切分后张量的大小。axis
:沿着哪个维度进行切分,默认为0。返回值:tf.split
返回一个张量列表。
示例:
num_or_size_splits为一个实数切分情况如下:
import tensorflow as tf
# 假设我们有以下的三维张量,形状为 (batch_size, height, width)
# 例如: (2, 6, 3),其中包含了2个6x3的矩阵
tensor = tf.reshape(tf.range(2*6*3), (2, 6, 3))
# 我们想要沿着height维度(即第二个维度,axis=1)把这个张量切分成3个大小相等的张量 (2, 2, 3)
split_tensors = tf.split(tensor, num_or_size_splits=3, axis=1)
for t in split_tensors:
print(t.numpy())
print("Shape:", t.shape)
执行后得到3个shape=(2,2,3)的张量的list。
split_tensors = tf.split(tensor, num_or_size_splits=[4, 2], axis=1)
for t in split_tensors:
print(t.numpy())
print("Shape:", t.shape)
得到2个形状分别为(2, 4, 3)
和(2, 2, 3)
的张量。
tf.keras.layers.Lambda
层可以让你定义简单的、单行的自定义运算作为一个层。这在你想要使用不直接映射到现有的标准层的表达式时特别有用。
Lambda
层的典型用法是将一个非线性函数(如ReLU、sigmoid)应用于输入,或者对输入进行简单的数学运算(如加法、乘法等)。你还可以使用Lambda
层来封装一个自定义的运算,使其能够与其他Keras层一起使用。
tf.keras.layers.Lambda(function, output_shape=None, mask=None, arguments=None)
function
:要应用的函数。这个函数需要接收一个输入张量,并返回一个输出张量。output_shape
:(可选)如果函数改变了输入张量的形状,则需要指定输出的形状。大多数情况下,不需要设置,因为Keras能自动推断出来。mask
:(可选)如果需要一个掩码来忽略某些输入,可以在这里指定。arguments
:(可选)如果函数需要额外的位置参数,可以通过这个参数传递一个字典来提供。gate权重设计利用lambda示例:
import tensorflow as tf
vec1=tf.constant([[1,1]],dtype=float)
vec2=tf.constant([[10,10]],dtype=float)
vec3=tf.constant([[100,100]],dtype=float)
gate_input=tf.constant([[1,2,3]],dtype=float)
vec_outs=[vec1,vec2,vec3]
# gate_out = tf.contrib.layers.fully_connected(gate_input, len(vec_outs), activation_fn=tf.nn.softmax,scope="gate")
gate_out = tf.keras.layers.Dense(units=len(vec_outs), activation='softmax')(gate_input) #与tf.contrib.layers.fully_connected等价
print("gate_out:",gate_out)
vec_out = tf.keras.layers.Lambda(lambda x: tf.stack(x, axis=1))(vec_outs) # None,len(vec_outs),dim
print("vec_out:",vec_out)
gate_out = tf.keras.layers.Lambda(lambda x: tf.expand_dims(x, axis=-1))(gate_out) # None,len(vec_outs),1
print("new gate_out:",gate_out)
gate_mul_vec= tf.keras.layers.Lambda(lambda x: tf.concat(x[0] * x[1], axis=1),
name='gate_mul_vec' )([vec_out, gate_out])
print("gate_mul_vec:",gate_mul_vec)
split_gate_out=tf.split(gate_mul_vec, num_or_size_splits=3, axis=1)
print("split_gate_out:",split_gate_out)
输出结果:
gate_out: tf.Tensor([[0.02509126 0.10217585 0.8727329 ]], shape=(1, 3), dtype=float32)
vec_out: tf.Tensor(
[[[ 1. 1.]
[ 10. 10.]
[100. 100.]]], shape=(1, 3, 2), dtype=float32)
new gate_out: tf.Tensor(
[[[0.02509126]
[0.10217585]
[0.8727329 ]]], shape=(1, 3, 1), dtype=float32)
gate_mul_vec: tf.Tensor(
[[[2.5091255e-02 2.5091255e-02]
[1.0217584e+00 1.0217584e+00]
[8.7273285e+01 8.7273285e+01]]], shape=(1, 3, 2), dtype=float32)
split_gate_out: [, , ]
在TensorFlow 2.0及更高版本中,tf.contrib
模块被弃用了,这意味着tf.contrib.layers.fully_connected
不再可用。取而代之的是,你应该使用tf.keras.layers.Dense
来创建全连接层(即密集层)。
下面二种方式等价
gate_out = tf.contrib.layers.fully_connected(gate_input, len(vec_outs), activation_fn=tf.nn.softmax,scope="gate")
gate_out = tf.keras.layers.Dense(units=len(vec_outs), activation='softmax',name='gate')(gate_input)
keras中Flatten层的用法及输入输出shape(附查看网络结构输入输出的查看技巧)_keras深度学习中如何输出flatten层的特征-CSDN博客
tf.split 与 tf.squeeze 用法 - 知乎