对于Tensorflow中dot()的运用以及对batch_dot()的理解

#dot
dot(x,y)
#求两个张量的乘积。当试图计算两个N阶张量的乘积时,与Theano行为相同
#如:(2,3).(4,3,5) =  (2,4,5)

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>

x = K.placeholder(shape=(32,28,3))
y = K.placeholder(shape=(3,4))
xy = K.dot(x,y)
xy
#输出为:<tf.Tensor 'MatMul_9:0' shape=(32, 28, 4) dtype=float32>

#Theano_like的行为示例
x = K.random_uniform_variable(shape=(2,3),low=0,hight=1)
y = K.ones((4,3,5))
xy = K.dot(x,y)
K.int_shape(xy)
#输出为:(2,4,5)

 

 


#batch_dot
batch_dot(x,y,axes=None)
#按批进行张量乘法,该函数用于计算x和y的点积,其中x和y都是成batch出现的数据。
#即它的数据shape形如(batch_size,:)。
#batch_dot将产生比输入张量维度低的张量,如果张量的维度被减至1,则通过expand_dims保证其维度至少为2 
#例如,假设x = [[1, 2],[3,4]] , y = [[5, 6],[7, 8]],则batch_dot(x, y, axes=1) = [[17, 53]],
#即x.dot(y.T)的主对角元素,此过程中我们没有计算过反对角元素的值

#对batch_dot的理解
x1 = tf.convert_to_tensor([[1,2,3],[4,5,6]])
x2 = tf.convert_to_tensor([[1,2,3],[4,5,6]])
K.batch_dot(x1,x2,axes=1).numpy()
#输出为:array([[14],
#      [77]], dtype=int32)

K.batch_dot(x1,x2,axes=0).numpy()
#输出为:array([[17],
#              [29],
#             [45]], dtype=int32)

#实际上其功能相当于:先将矩阵进行对位乘法,然后再按照axes轴进行聚合加法。
#验证代码如下:

tf.reduce_sum(tf.multiply(x1 , x2) , axis=1).numpy()
#输出为:array([14, 77], dtype=int32)

tf.reduce_sum(tf.multiply(x1 , x2) , axis=0).numpy()
#输出为:array([17, 29, 45], dtype=int32)

 

 

#对于输出shape 的推导:
#假设x是一个shape为(100,20)的tensor,
#y是一个shape为(100,30,20)的tensor,
#假设axes=(1,2),则输出tensor的shape通过循环x.shape和y.shape确定:
#x.shape[0]:值为100,加入到输入shape里
#x.shape[1]:20,不加入输出shape里,因为该维度的值会被求和(dot_axes[0]=1)
#y.shape[0]:值为100,不加入到输出shape里,y的第一维总是被忽略
#y.shape[1]:30,加入到输出shape里
#y.shape[2]:20,不加到output shape里,y的第二个维度会被求和(dot_axes[1]=2)

#结果为(100, 30)

x_batch = K.ones(shape=(32,20,1))
y_batch = K.ones(shape=(32,30,20))
xy_batch_dot = K.batch_dot(x_batch,y_batch,axes=[1,2])
K.int_shape(xy_batch_dot)
#输出为:(32,1,30)

#模拟输出shape的过程如下:
#先加入32,由于axes[0]=1,所以不加入20,加入1,跳过y的第一维,加入30,由于axes[1]=2,所以不加入20
 

含义 Multi-Head Self-Attention是一种注意力机制(Attention Mechanism)的实现方式,用于处理序列数据,例如自然语言处理中的句子。在Multi-Head Self-Attention中,输入序列通过多个不同的注意力头(Attention Head)进行处理,每个头都会计算出不同的注意力分布,最终将这些分布进行加权平均得到最终的输出。这种方法可以捕捉序列中不同位置之间的关系,提高序列数据的表现力。 实现 在tensorflow中,Multi-Head Self-Attention通常作为Transformer模型的核心部分,由以下几个步骤实现: 1. 首先,使用线性变换将输入序列映射到多个不同的维度空间,得到多个不同的查询(Query)、键(Key)和值(Value)向量。 2. 对于每个注意力头,计算查询向量与键向量之间的点积(Dot-Product Attention),并将得到的值除以一个缩放因子,以避免点积过大或过小的问题。然后,通过softmax函数将得到的分数转换为注意力分布。 3. 将注意力分布与值向量相乘,得到每个头的输出向量。 4. 将多个头的输出向量连接在一起,并通过线性变换得到最终的输出向量。 以下是一个简单的tensorflow实现代码示例: ``` import tensorflow as tf from tensorflow.keras.layers import Layer class MultiHeadAttention(Layer): def __init__(self, num_heads, d_model): super(MultiHeadAttention, self).__init__() self.num_heads = num_heads self.d_model = d_model assert d_model % self.num_heads == 0 self.depth = d_model // self.num_heads self.query_dense = tf.keras.layers.Dense(units=d_model) self.key_dense = tf.keras.layers.Dense(units=d_model) self.value_dense = tf.keras.layers.Dense(units=d_model) self.dense = tf.keras.layers.Dense(units=d_model) def split_heads(self, inputs, batch_size): inputs = tf.reshape(inputs, shape=(batch_size, -1, self.num_heads, self.depth)) return tf.transpose(inputs, perm=[0, 2, 1, 3]) def call(self, inputs): query, key, value = inputs['query'], inputs['key'], inputs['value'] batch_size = tf.shape(query)[0] query = self.query_dense(query) key = self.key_dense(key) value = self.value_dense(value) query = self.split_heads(query, batch_size) key = self.split_heads(key, batch_size) value = self.split_heads(value, batch_size) scaled_attention_logits = tf.matmul(query, key, transpose_b=True) scaled_attention_logits = scaled_attention_logits / tf.math.sqrt(tf.cast(self.depth, tf.float32)) attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1) attention_output = tf.matmul(attention_weights, value) attention_output = tf.transpose(attention_output, perm=[0, 2, 1, 3]) concat_attention = tf.reshape(attention_output, (batch_size, -1, self.d_model)) output = self.dense(concat_attention) return output ``` 在这个实现中,我们通过定义一个MultiHeadAttention类来实现Multi-Head Self-Attention。在初始化函数中,我们指定了注意力头的数量和注意力向量的维度,然后通过三个线性层来映射输入序列到不同的维度空间。在call函数中,我们首先将输入序列分别通过这三个线性层进行变换,然后将它们分割成多个头,并计算出每个头的注意力分布。最后,我们将多个头的输出向量连接在一起,并通过一个线性层得到最终的输出向量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值