鱼C论坛

 找回密码
 立即注册
查看: 2552|回复: 17

[已解决]transformer模型怎么用tensorflow搭建

[复制链接]
发表于 2023-12-25 09:49:36 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
怎么用tensorflow来搭建transformer模型并实现时间序列预测?
@FishC
最佳答案
2023-12-25 09:57:35
WTMGCLGGA 发表于 2023-12-25 09:56
可以输出一个完整的transformer模型吗,需要包括定义 ...

当然可以!下面是一个用TensorFlow实现的Transformer模型的完整代码。首先,让我们从导入必要的库开始:
  1. import tensorflow as tf
  2. import numpy as np
复制代码

接下来,我们定义一些超参数:
  1. NUM_LAYERS = 2  # 编码器和解码器的层数
  2. D_MODEL = 32  # 模型的维度
  3. NUM_HEADS = 4  # 多头注意力机制的头数
  4. UNITS = 64 # 前向传播层的神经元数量
  5. DROPOUT_RATE = 0.1  # Dropout的概率
  6. N_FEATURES = 5  # 输入时间序列的特征数量
复制代码

然后我们来定义编码器和解码器中的一些子层:多头注意力机制层、前向传播层、位置编码层和掩码层。
  1. class MultiHeadAttention(tf.keras.layers.Layer):
  2.     def __init__(self, d_model, num_heads):
  3.         super(MultiHeadAttention, self).__init__()
  4.         self.num_heads = num_heads
  5.         self.d_model = d_model
  6.         
  7.         assert d_model % self.num_heads == 0
  8.         
  9.         self.depth = d_model // self.num_heads
  10.         
  11.         self.wq = tf.keras.layers.Dense(d_model)
  12.         self.wk = tf.keras.layers.Dense(d_model)
  13.         self.wv = tf.keras.layers.Dense(d_model)
  14.         
  15.         self.dense = tf.keras.layers.Dense(d_model)
  16.         
  17.     def split_heads(self, x, batch_size):
  18.         x = tf.reshape(x, (batch_size, -1, self.num_heads, self.depth))
  19.         return tf.transpose(x, perm=[0, 2, 1, 3])
  20.    
  21.     def call(self, v, k, q, mask):
  22.         batch_size = tf.shape(q)[0]
  23.         
  24.         q = self.wq(q)
  25.         k = self.wk(k)
  26.         v = self.wv(v)
  27.         
  28.         q = self.split_heads(q, batch_size)
  29.         k = self.split_heads(k, batch_size)
  30.         v = self.split_heads(v, batch_size)
  31.         
  32.         scaled_attention_logits = tf.matmul(q, k, transpose_b=True)  
  33.         
  34.         scaled_attention_logits /= tf.math.sqrt(tf.cast(self.depth, tf.float32))
  35.         
  36.         if mask is not None:
  37.             scaled_attention_logits += (mask * -1e9)
  38.         
  39.         attention_weights = tf.nn.softmax(scaled_attention_logits, axis=-1)
  40.         
  41.         output = tf.matmul(attention_weights, v)
  42.         output = tf.transpose(output, perm=[0, 2, 1, 3])
  43.         output = tf.reshape(output, (batch_size, -1, self.d_model))
  44.         
  45.         output = self.dense(output)
  46.         
  47.         return output, attention_weights
  48. class PointWiseFeedForwardNetwork(tf.keras.layers.Layer):
  49.     def __init__(self, d_model, num_units):
  50.         super(PointWiseFeedForwardNetwork, self).__init__()
  51.         self.d_model = d_model
  52.         self.num_units = num_units
  53.         
  54.         self.fc1 = tf.keras.layers.Dense(num_units, activation=tf.nn.relu)
  55.         self.fc2 = tf.keras.layers.Dense(d_model)
  56.         
  57.     def call(self, x):
  58.         output = self.fc1(x)
  59.         output = self.fc2(output)
  60.         return output
  61.       
  62. class PositionalEncoding(tf.keras.layers.Layer):
  63.     def __init__(self, position, d_model):
  64.         super(PositionalEncoding, self).__init__()
  65.         self.position = position
  66.         self.d_model = d_model
  67.         
  68.         self.pos_encoding = self.positional_encoding(position, d_model)
  69.         
  70.     def get_angles(self, position, i, d_model):
  71.         angles = 1 / tf.pow(10000, (2 * (i // 2)) / tf.cast(d_model, tf.float32))
  72.         return position * angles
  73.    
  74.     def positional_encoding(self, position, d_model):
  75.         angle_rads = self.get_angles(
  76.             position=tf.range(position, dtype=tf.float32)[:, tf.newaxis],
  77.             i=tf.range(d_model, dtype=tf.float32)[tf.newaxis, :],
  78.             d_model=d_model)
  79.         
  80.         sines = tf.math.sin(angle_rads[:, 0::2])
  81.         cosines = tf.math.cos(angle_rads[:, 1::2])
  82.         
  83.         pos_encoding = tf.concat([sines, cosines], axis=-1)
  84.         pos_encoding = pos_encoding[tf.newaxis, ...]
  85.         
  86.         return tf.cast(pos_encoding, tf.float32)
  87.    
  88.     def call(self, inputs):
  89.         return inputs + self.pos_encoding[:, :tf.shape(inputs)[1], :]
  90.       
  91. def create_padding_mask(seq):
  92.     seq = tf.cast(tf.math.equal(seq, 0), tf.float32)
  93.     return seq[:, tf.newaxis, tf.newaxis, :]  # 在最后添加额外的维度以符合multi-head attention的要求
复制代码

接下来,我们定义编码器和解码器:
  1. class EncoderLayer(tf.keras.layers.Layer):
  2.     def __init__(self, d_model, num_heads, units, dropout_rate):
  3.         super(EncoderLayer, self).__init__()
  4.         self.mha = MultiHeadAttention(d_model, num_heads)
  5.         self.ffn = PointWiseFeedForwardNetwork(d_model, units)
  6.         
  7.         self.layer_norm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
  8.         self.layer_norm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
  9.         
  10.         self.dropout1 = tf.keras.layers.Dropout(dropout_rate)
  11.         self.dropout2 = tf.keras.layers.Dropout(dropout_rate)
  12.         
  13.     def call(self, x, training, mask):
  14.         attn_output, _ = self.mha(x, x, x, mask)  
  15.         attn_output = self.dropout1(attn_output, training=training)
  16.         out1 = self.layer_norm1(x + attn_output)  
  17.         
  18.         ffn_output = self.ffn(out1)
  19.         ffn_output = self.dropout2(ffn_output, training=training)
  20.         out2 = self.layer_norm2(out1 + ffn_output)  
  21.         
  22.         return out2
  23. class DecoderLayer(tf.keras.layers.Layer):
  24.     def __init__(self, d_model, num_heads, units, dropout_rate):
  25.         super(DecoderLayer, self).__init__()
  26.         self.mha1 = MultiHeadAttention(d_model, num_heads)
  27.         self.mha2 = MultiHeadAttention(d_model, num_heads)
  28.         
  29.         self.ffn = PointWiseFeedForwardNetwork(d_model, units)
  30.         
  31.         self.layer_norm1 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
  32.         self.layer_norm2 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
  33.         self.layer_norm3 = tf.keras.layers.LayerNormalization(epsilon=1e-6)
  34.         
  35.         self.dropout1 = tf.keras.layers.Dropout(dropout_rate)
  36.         self.dropout2 = tf.keras.layers.Dropout(dropout_rate)
  37.         self.dropout3 = tf.keras.layers.Dropout(dropout_rate)
  38.         
  39.     def call(self, x, enc_output, training,
  40.            look_ahead_mask, padding_mask):
  41.         attn1, attn_weights_block1 = self.mha1(x, x, x, look_ahead_mask)
  42.         attn1 = self.dropout1(attn1, training=training)
  43.         out1 = self.layer_norm1(attn1 + x)
  44.         
  45.         attn2, attn_weights_block2 = self.mha2(
  46.             enc_output, enc_output, out1, padding_mask)  
  47.         attn2 = self.dropout2(attn2, training=training)
  48.         out2 = self.layer_norm2(attn2 + out1)  
  49.         
  50.         ffn_output = self.ffn(out2)  
  51.         ffn_output = self.dropout3(ffn_output, training=training)
  52.         out3 = self.layer_norm3(ffn_output + out2)  
  53.         
  54.         return out3, attn_weights_block1, attn_weights_block2
复制代码

然后是编码器和解码器的堆叠:
  1. class Encoder(tf.keras.layers.Layer):
  2.     def __init__(self, num_layers, d_model, num_heads, units, dropout_rate,
  3.                max_seq_len):
  4.         super(Encoder, self).__init__()
  5.         self.d_model = d_model
  6.         self.num_layers = num_layers
  7.         
  8.         self.embedding = tf.keras.layers.Dense(d_model)
  9.         self.pos_encoding = PositionalEncoding(max_seq_len, d_model)
  10.         self.enc_layers = [EncoderLayer(d_model, num_heads, units,
  11.                                        dropout_rate) for _ in range(num_layers)]
  12.         
  13.     def call(self, x, training, mask):
  14.         x = self.embedding(x)
  15.         x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
  16.         x = self.pos_encoding(x)
  17.         
  18.         for i in range(self.num_layers):
  19.             x = self.enc_layers[i](x, training, mask)
  20.             
  21.         return x
  22. class Decoder(tf.keras.layers.Layer):
  23.     def __init__(self, num_layers, d_model, num_heads, units, dropout_rate,
  24.                max_seq_len):
  25.         super(Decoder, self).__init__()
  26.         self.d_model = d_model
  27.         self.num_layers = num_layers
  28.         
  29.         self.embedding = tf.keras.layers.Dense(d_model)
  30.         self.pos_encoding = PositionalEncoding(max_seq_len, d_model)
  31.         self.dec_layers = [DecoderLayer(d_model, num_heads, units,
  32.                                         dropout_rate) for _ in range(num_layers)]
  33.         
  34.     def call(self, x, enc_output, training,
  35.            look_ahead_mask, padding_mask):
  36.         x = self.embedding(x)
  37.         x *= tf.math.sqrt(tf.cast(self.d_model, tf.float32))
  38.         x = self.pos_encoding(x)
  39.         
  40.         for i in range(self.num_layers):
  41.             x, block1, block2 = self.dec_layers[i](x, enc_output, training,
  42.                                                   look_ahead_mask, padding_mask)
  43.         
  44.         return x
复制代码

最后,我们定义Transformer模型:
  1. class Transformer(tf.keras.Model):
  2.     def __init__(self, num_layers, d_model, num_heads, units, dropout_rate,
  3.                max_seq_len):
  4.         super(Transformer, self).__init__()
  5.         self.encoder = Encoder(num_layers, d_model, num_heads, units,
  6.                                dropout_rate, max_seq_len)
  7.         self.decoder = Decoder(num_layers, d_model, num_heads, units,
  8.                                dropout_rate, max_seq_len)
  9.         self.final_layer = tf.keras.layers.Dense(1)
  10.         
  11.     def call(self, inp, tar, training, enc_padding_mask,
  12.              look_ahead_mask, dec_padding_mask):
  13.         enc_output = self.encoder(inp, training, enc_padding_mask)
  14.         
  15.         dec_output = self.decoder(
  16.             tar, enc_output, training, look_ahead_mask, dec_padding_mask)
  17.         
  18.         final_output = self.final_layer(dec_output)
  19.         
  20.         return final_output
复制代码

在定义完整的Transformer模型之后,我们可以使用随机生成的时间序列数据进行测试。假设我们有`N`个样本,每个样本包含`t`个时间步和`F`个特征。下面是一个示例:
  1. # 生成随机时间序列数据
  2. N = 1000
  3. t = 10
  4. F = 5
  5. X = np.random.rand(N, t, F)
  6. y = np.random.rand(N, 1)
  7. # 划分训练集和测试集
  8. train_ratio = 0.8
  9. train_size = int(N * train_ratio)
  10. X_train, X_test = X[:train_size], X[train_size:]
  11. y_train, y_test = y[:train_size], y[train_size:]
  12. # 创建掩码
  13. train_padding_mask = create_padding_mask(X_train[:, :, 0])
  14. train_look_ahead_mask = create_look_ahead_mask(tf.shape(X_train)[1])
  15. train_dec_padding_mask = create_padding_mask(X_train[:, :, 0])
  16. # 设置超参数
  17. num_layers = 2
  18. d_model = 32
  19. num_heads = 4
  20. units = 64
  21. dropout_rate = 0.1
  22. max_seq_len = t
  23. # 创建和训练模型
  24. model = Transformer(num_layers, d_model, num_heads, units,
  25.                     dropout_rate, max_seq_len)
  26. loss_object = tf.keras.losses.MeanSquaredError()
  27. optimizer = tf.keras.optimizers.Adam()
  28. train_loss = tf.keras.metrics.Mean(name='train_loss')
  29. train_accuracy = tf.keras.metrics.MeanSquaredError(name='train_mse')
  30. @tf.function
  31. def train_step(inp, tar):
  32.     tar_inp = tar[:, :-1]
  33.     tar_real = tar[:, 1:]
  34.    
  35.     with tf.GradientTape() as tape:
  36.         predictions = model(inp, tar_inp, True,
  37.                             train_padding_mask,
  38.                             train_look_ahead_mask,
  39.                             train_dec_padding_mask)
  40.         loss = loss_function(tar_real, predictions)
  41.         
  42.     gradients = tape.gradient(loss, model.trainable_variables)
  43.     optimizer.apply_gradients(zip(gradients, model.trainable_variables))
  44.    
  45.     train_loss(loss)
  46.     train_accuracy(tar_real, predictions)
  47.    
  48. EPOCHS = 10
  49. BATCH_SIZE = 16
  50. for epoch in range(EPOCHS):
  51.     train_loss.reset_states()
  52.     train_accuracy.reset_states()
  53.    
  54.     for i in range(0, train_size, BATCH_SIZE):
  55.         inp = X_train[i:i+BATCH_SIZE]
  56.         tar = y_train[i:i+BATCH_SIZE]
  57.         train_step(inp, tar)
  58.         
  59.     print(f'Epoch {epoch+1}, Loss: {train_loss.result()}, MSE: {train_accuracy.result()}')
  60. # 进行测试
  61. test_padding_mask = create_padding_mask(X_test[:, :, 0])
  62. test_look_ahead_mask = create_look_ahead_mask(tf.shape(X_test)[1])
  63. test_dec_padding_mask = create_padding_mask(X_test[:, :, 0])
  64. predictions = model(X_test, X_test[:, :-1], False,
  65.                     test_padding_mask,
  66.                     test_look_ahead_mask,
  67.                     test_dec_padding_mask)
  68. test_loss = loss_object(y_test[:, 1:], predictions)
  69. print(f'Test Loss: {test_loss}, MSE: {tf.reduce_mean(tf.square(y_test[:, 1:] - predictions))}')
复制代码

上面的代码演示了如何构建和训练一个Transformer模型,以及如何使用训练模型进行预测。希望对你有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-12-25 09:51:34 | 显示全部楼层
transformer应该还需要定义位置编码层吧@FishC
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-25 09:52:41 | 显示全部楼层
这个是使用pytorch实现的位置编码层,怎么用tensorflow来定义位置编码层呢@FishC
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-25 09:56:58 | 显示全部楼层
FishC 发表于 2023-12-25 09:52
嗨!要使用TensorFlow定义位置编码层,我们可以参考一下PyTorch版的代码来实现。

在PyTorch版本的代码中 ...

可以输出一个完整的transformer模型吗,需要包括定义编码器、解码器、多头注意力机制层、前向传播层、位置编码层、掩码层,然后是随机生成一个时间序列来训练并测试,使用前5个时间步的5个特征预测未来一个时间步的1个特征,使用tensorflow进行搭建
@FishC
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-25 10:10:54 | 显示全部楼层
FishC 发表于 2023-12-25 09:57
当然可以!下面是一个用TensorFlow实现的Transformer模型的完整代码。首先,让我们从导入必要的库开始:
...

train_look_ahead_mask = create_look_ahead_mask(tf.shape(X_train)[1])
这一行的create_look_ahead_mask还没有定义过吧
@FishC
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-25 10:15:32 | 显示全部楼层
FishC 发表于 2023-12-25 10:11
是的,您说得对。在这一行中,create_look_ahead_mask函数还没有定义过。

根据命名约定,这个函数应该是 ...

ValueError                                Traceback (most recent call last)
Cell In[14], line 10
      8     inp = X_train[i:i+BATCH_SIZE]
      9     tar = y_train[i:i+BATCH_SIZE]
---> 10     train_step(inp, tar)
     12 print(f'Epoch {epoch+1}, Loss: {train_loss.result()}, MSE: {train_accuracy.result()}')
运行时出现了这个错误@FishC
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-26 09:17:06 | 显示全部楼层
怎么将一个pytorch写的transformer模型转换成tensorflow
@FishC
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-26 09:20:34 | 显示全部楼层
class PositionalEncoding(nn.Module):
    def __init__(self,d_model,max_len=5000):
        super(PositionalEncoding,self).__init__()

        pe=torch.zeros(max_len,d_model)
        position=torch.arange(0,max_len,dtype=torch.float).unsqueeze(1)
        div_term=torch.exp(torch.arange(0,d_model,2).float()*(-math.log(10000.0)/d_model))

        pe[:,0::2]=torch.sin(position*div_term)
        pe[:,1::2]=torch.cos(position*div_term)

        pe=pe.unsqueeze(0).transpose(0,1)
        self.register_buffer('pe',pe)
   
    def forward(self,x:torch.Tensor):
        chunk=x.chunk(x.size(-1),dim=2)
        out=torch.Tensor([]).to(x.device)

        for i in range(len(chunk)):
            out=torch.cat((out,chunk[i]+self.pe[:chunk[i].size(0),...]),dim=2)

        return out

def transformer_generate_tgt_mask(length,device):
    mask=torch.tril(torch.ones(length,length,device=device))==1
    mask=(
        mask.float()
        .masked_fill(mask==0,float("-inf"))
        .masked_fill(mask==1,float(0.0))
    )

    return mask

class Transformer(nn.Module):
    def __init__(self,n_encoder_inputs,n_decoder_inputs,Sequence_length,d_model=512,dropout=0.1,num_layer=8):
        super(Transformer,self).__init__()
        
        self.input_pos_embedding=torch.nn.Embedding(500,embedding_dim=d_model)
        self.target_pos_embedding=torch.nn.Embedding(500,embedding_dim=d_model)
        
        encoder_layer=torch.nn.TransformerEncoderLayer(d_model=d_model,nhead=num_layer,dropout=dropout,dim_feedforward=4*d_model)
        decoder_layer=torch.nn.TransformerDecoderLayer(d_model=d_model,nhead=num_layer,dropout=dropout,dim_feedforward=4*d_model)
        
        self.encoder=torch.nn.TransformerEncoder(encoder_layer,num_layers=2)
        self.decoder=torch.nn.TransformerDecoder(decoder_layer,num_layers=4)
        
        self.lstm=nn.LSTM(len_int,len_int,num_layers=1,bidirectional=False)
        self.input_projection=torch.nn.Linear(n_encoder_inputs,d_model)
        self.output_projection=torch.nn.Linear(n_decoder_inputs,d_model)
        
        self.linear=torch.nn.Linear(d_model,1)
        self.ziji_add_linear=torch.nn.Linear(Sequence_length,1)
        self.relu=F.relu
   
    def encode_in(self,src):
        src_start=self.input_projection(src).permute(1,0,2)
        in_sequence_len,batch_size=src_start.size(0),src_start.size(1)
        
        pos_encoder=(torch.arange(0,in_sequence_len,device=src.device).unsqueeze(0).repeat(batch_size,1))
        pos_encoder=self.input_pos_embedding(pos_encoder).permute(1,0,2)

        src=src_start+pos_encoder
        src=self.encoder(src)+src_start
        return src
   
    def decode_out(self,tgt,memory):
        tgt_start=self.output_projection(tgt).permute(1,0,2)
        out_sequence_len,batch_size=tgt_start.size(0),tgt_start.size(1)

        pos_decoder=(torch.arange(0,out_sequence_len,device=tgt.device).unsqueeze(0).repeat(batch_size,1))
        pos_decoder=self.target_pos_embedding(pos_decoder).permute(1,0,2)

        tgt=tgt_start+pos_decoder
        tgt_mask=transformer_generate_tgt_mask(out_sequence_len,tgt.device)

        out=self.decoder(tgt=tgt,memory=memory,tgt_mask=tgt_mask)+tgt_start
        out=out.permute(1,0,2)
        out=self.linear(out)
        return out
        
    def forward(self,src,target_in):
        lstm_out,(h_n,c_n)=self.lstm(src)
        src=self.encode_in(self.relu(lstm_out))
        out=self.decode_out(tgt=target_in,memory=src)
        out=out.squeeze(2)
        out=self.ziji_add_linear(out)
        return out
这是一个pytorch写的transformer模型,能不能将它转换成tensorflow代码
@FishC
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-12-26 09:31:04 | 显示全部楼层
我需要用transformer模型解决一个时间序列预测问题,使用前5个时间步的5个特征来预测未来1个时间步的1个特征,请用tensorflow帮我写一个transformer模型,需要包括定义编码器、解码器、位置编码层、掩码层、多头注意力机制层、前向传播层、各个子层之间的残差连接和标准化层,等transformer结构中需要的层
@FishC
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-9-22 08:08

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表