TensorFlow从入门到实践:TensorFlow文本生成入门-从预处理到模型实践

部署运行你感兴趣的模型镜像

项目实践:文本生成

学习目标

通过本课程,你将掌握如何使用TensorFlow构建文本生成模型,了解文本数据的预处理方法,以及如何利用RNN或Transformer模型生成新的文本内容。本课程将通过实际项目,帮助你从理论到实践全面掌握文本生成技术。

相关知识点

  • 文本处理与RNN/Transformer模型

学习内容

1 文本处理与RNN/Transformer模型

1.1 文本数据预处理

在开始构建文本生成模型之前,首先需要对文本数据进行预处理。文本数据预处理是自然语言处理(NLP)任务中的重要步骤,它直接影响到模型的性能。预处理步骤通常包括文本清洗、分词、构建词汇表、向量化等。

文本清洗

文本清洗是指去除文本中的噪声,如HTML标签、特殊字符、数字等,只保留有用的文本信息。这一步骤可以使用正则表达式来实现。例如,我们可以使用Python的re库来去除文本中的数字和特殊字符。

import re

def clean_text(text):
    # 去除数字
    text = re.sub(r'\d+', '', text)
    # 去除特殊字符
    text = re.sub(r'[^\w\s]', '', text)
    return text

# 示例
text = "Hello, World! 123"
cleaned_text = clean_text(text)
print(cleaned_text)  # 输出: Hello World

分词

分词是将文本分割成单词或词组的过程。分词的目的是将文本转换为模型可以处理的形式。常用的分词工具包括NLTK、spaCy等。以下是一个使用NLTK进行分词的示例:
安装必要的库

%pip install nltk
%pip install tensorflow
%pip install --upgrade numpy ml-dtypes
!wget https://model-community-picture.obs.cn-north-4.myhuaweicloud.com/ascend-zone/notebook_datasets/a05f02c0523a11f08d69f8fe5e46a8fb/nltk_data.zip
!unzip nltk_data.zip
import nltk
import os

# 添加nltk_data文件夹到NLTK的数据路径中
nltk.data.path.append(os.path.join(os.getcwd(), 'nltk_data'))


def tokenize(text):
    return nltk.word_tokenize(text)

# 示例
text = "Hello, World!"
tokens = tokenize(text)
print(tokens)  # 输出: ['Hello', ',', 'World', '!']

构建词汇表

构建词汇表是将文本中的单词映射到唯一的整数ID。这一步骤可以使用TensorFlow的tf.keras.preprocessing.text.Tokenizer类来实现。以下是一个示例:

from tensorflow.keras.preprocessing.text import Tokenizer

def build_vocab(texts, num_words=None):
    tokenizer = Tokenizer(num_words=num_words)
    tokenizer.fit_on_texts(texts)
    return tokenizer

# 示例
texts = ["Hello, World!", "Hello, TensorFlow!"]
tokenizer = build_vocab(texts, num_words=10000)
word_index = tokenizer.word_index
print(word_index)  # 输出: {'hello': 1, 'world': 2, 'tensorflow': 3}
from tensorflow.keras.preprocessing.text import Tokenizer
import re

def preprocess_text(text):
    """
    预处理文本,移除标点符号和特殊字符。
    """
    text = re.sub(r'[^\w\s]', '', text)  # 移除标点符号
    text = text.lower()  # 转换为小写
    return text

def build_vocab(texts, num_words=None):
    """
    构建词汇表。
    :param texts: 文本列表
    :param num_words: 词汇表的最大大小
    :return: Tokenizer 对象
    """
    # 预处理文本
    texts = [preprocess_text(text) for text in texts]
    
    tokenizer = Tokenizer(num_words=num_words)
    tokenizer.fit_on_texts(texts)
    return tokenizer

# 示例
texts = ["Hello, World!", "Hello, TensorFlow!"]
tokenizer = build_vocab(texts, num_words=10000)
word_index = tokenizer.word_index
print(word_index)  # 输出: {'hello': 1, 'world': 2, 'tensorflow': 3}

向量化

向量化是将文本转换为数值形式,以便模型可以处理。常见的向量化方法包括词袋模型(Bag of Words)、TF-IDF、词嵌入等。以下是一个使用词嵌入的示例:

from tensorflow.keras.preprocessing.sequence import pad_sequences

def vectorize_texts(texts, tokenizer, max_length):
    sequences = tokenizer.texts_to_sequences(texts)
    padded_sequences = pad_sequences(sequences, maxlen=max_length, padding='post')
    return padded_sequences

# 示例
texts = ["Hello, World!", "Hello, TensorFlow!"]
tokenizer = build_vocab(texts, num_words=10000)
padded_sequences = vectorize_texts(texts, tokenizer, max_length=10)
print(padded_sequences)  # 输出: [[1, 2, 0, 0, 0, 0, 0, 0, 0, 0], [1, 3, 0, 0, 0, 0, 0, 0, 0, 0]]
1.2 RNN模型构建与训练

循环神经网络(RNN)是一种专门用于处理序列数据的神经网络架构。它能够有效地捕捉序列中的时间依赖关系,即当前数据点与之前数据点之间的关联。这种特性使得RNN在处理具有时间顺序或上下文关系的数据时表现出色,非常适合用于文本生成任务。例如,在生成文本时,RNN可以根据前面的单词来预测下一个单词,从而生成连贯的句子。接下来将深入学习如何使用TensorFlow来构建和训练RNN模型,掌握如何利用其强大的功能来处理各种序列数据任务,包括但不限于文本生成、时间序列预测等。通过实践,你将能够更好地理解RNN的工作原理以及如何优化模型以获得更好的性能。

RNN模型构建

构建RNN模型的基本步骤包括定义模型结构、编译模型和训练模型。以下是一个使用TensorFlow构建RNN模型的示例:

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, SimpleRNN, Dense, Input

def build_rnn_model(vocab_size, embedding_dim, rnn_units, batch_size):
    model = Sequential([
        Input(batch_shape=(batch_size, None)),  # 使用 Input 层指定输入形状
        Embedding(vocab_size, embedding_dim),
        SimpleRNN(rnn_units, return_sequences=True, stateful=True),
        Dense(vocab_size)
    ])
    return model

# 参数设置
vocab_size = 10000
embedding_dim = 256
rnn_units = 1024
batch_size = 64

# 构建模型
model = build_rnn_model(vocab_size, embedding_dim, rnn_units, batch_size)
model.summary()

RNN模型训练

训练RNN模型需要定义损失函数和优化器。对于文本生成任务,常用的损失函数是交叉熵损失(Cross-Entropy Loss),优化器可以使用Adam。以下是一个训练RNN模型的示例:

import tensorflow as tf
import numpy as np
import os
import random
import string

# 1. 数据生成函数
def generate_text_data(num_samples=10000, min_len=50, max_len=200):
    """生成随机文本数据用于训练"""
    print("Generating synthetic text data...")
    samples = []
    
    # 定义生成随机单词的函数
    def random_word(length):
        return ''.join(random.choice(string.ascii_lowercase + ' ') for _ in range(length))
    
    # 生成样本
    for _ in range(num_samples):
        # 随机决定句子长度
        sentence_len = random.randint(min_len, max_len)
        # 生成由随机单词和空格组成的句子
        sentence = ' '.join([random_word(random.randint(1, 10)) for _ in range(sentence_len)])
        samples.append(sentence)
    
    # 合并所有样本为一个长文本
    full_text = '\n'.join(samples)
    return full_text

# 2. 数据准备
def prepare_dataset(text, seq_length=100, batch_size=64):
    """准备数据集"""
    print("Preparing dataset...")
    # 创建字符到索引的映射
    vocab = sorted(set(text))
    char2idx = {u:i for i, u in enumerate(vocab)}
    idx2char = np.array(vocab)
    
    # 将文本转换为数字
    text_as_int = np.array([char2idx[c] for c in text])
    
    # 创建训练样本
    char_dataset = tf.data.Dataset.from_tensor_slices(text_as_int)
    
    # 生成序列
    sequences = char_dataset.batch(seq_length+1, drop_remainder=True)
    
    # 分割输入和目标
    def split_input_target(chunk):
        input_text = chunk[:-1]
        target_text = chunk[1:]
        return input_text, target_text
    
    dataset = sequences.map(split_input_target)
    
    # 批处理和打乱数据
    dataset = dataset.shuffle(10000).batch(batch_size, drop_remainder=True)
    
    return dataset, vocab, char2idx, idx2char

# 3. 构建RNN模型
def build_rnn_model(vocab_size, embedding_dim=256, rnn_units=1024, batch_size=64):
    """构建RNN模型"""
    print("Building model...")
    model = tf.keras.Sequential([
        tf.keras.layers.Embedding(vocab_size, embedding_dim),
        tf.keras.layers.GRU(rnn_units,
                          return_sequences=True,
                          stateful=True,
                          recurrent_initializer='glorot_uniform'),
        tf.keras.layers.Dense(vocab_size)
    ])
    model.build(input_shape=(batch_size, None))
    return model

# 4. 训练函数
def train_rnn_model(model, dataset, epochs, checkpoint_dir):
    """训练模型"""
    # 创建检查点目录
    os.makedirs(checkpoint_dir, exist_ok=True)
    
    # 定义检查点路径 - 确保以.weights.h5结尾
    checkpoint_path = os.path.join(checkpoint_dir, "ckpt.weights.h5")
    
    # 定义回调函数
    checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(
        filepath=checkpoint_path,
        save_weights_only=True,
        save_best_only=False,
        verbose=1)
    
    # 编译模型
    model.compile(optimizer='adam',
                loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                metrics=['accuracy'])
    
    # 训练模型
    print("Training model...")
    history = model.fit(dataset,
                      epochs=epochs,
                      callbacks=[checkpoint_callback])
    return history

# 5. 文本生成函数
def generate_text(model, start_string, char2idx, idx2char, num_generate=100):
    """使用训练好的模型生成文本"""
    # 将起始字符串转换为数字(向量化)
    input_eval = [char2idx[s] for s in start_string]
    input_eval = tf.expand_dims(input_eval, 0)

    # 空字符串用于存储结果
    text_generated = []

    # 这里批大小为1
    for i in range(num_generate):
        predictions = model(input_eval)
        # 移除批次的维度
        predictions = tf.squeeze(predictions, 0)

        # 用分类分布预测模型返回的字符
        predicted_id = tf.random.categorical(predictions, num_samples=1)[-1,0].numpy()

        # 把预测字符和前面的隐藏状态一起传递给模型作为下一步输入
        input_eval = tf.expand_dims([predicted_id], 0)

        text_generated.append(idx2char[predicted_id])

    return (start_string + ''.join(text_generated))

# 6. 主程序
def main():
    # 生成训练数据
    text_data = "hello world this is a test " * 1000 
    print(f"Generated text length: {len(text_data)} characters")
    print("Sample text:", text_data[:200] + "...")
    
    # 准备数据集
    seq_length = 20  
    batch_size = 32  
    dataset, vocab, char2idx, idx2char = prepare_dataset(text_data, seq_length, batch_size)
    vocab_size = len(vocab)
    print(f"Vocabulary size: {vocab_size}")
    print("Vocabulary:", ''.join(vocab))
    
    # 构建模型
    embedding_dim = 64 
    rnn_units = 128     
    model = build_rnn_model(vocab_size, embedding_dim, rnn_units, batch_size)
    model.summary()
    
    # 训练模型
    epochs = 10
    checkpoint_dir = './training_checkpoints'
    train_rnn_model(model, dataset, epochs, checkpoint_dir)
    
    # 保存最终模型
    final_model = tf.keras.Sequential([
        tf.keras.layers.Embedding(vocab_size, embedding_dim),
        tf.keras.layers.GRU(rnn_units,
                          return_sequences=True,
                          stateful=False, 
                          recurrent_initializer='glorot_uniform'),
        tf.keras.layers.Dense(vocab_size)
    ])
    final_model.build(input_shape=(1, None))
    
    # 加载最佳权重 - 确保检查点存在
    checkpoint_path = os.path.join(checkpoint_dir, "ckpt.weights.h5")
    if os.path.exists(checkpoint_path):
        final_model.load_weights(checkpoint_path)
        print("Successfully loaded weights from checkpoint")
    else:
        print("No checkpoint found, using untrained model")
    
    # 保存完整模型
    final_model.save('text_generation_model.keras')
    
    # 演示文本生成
    print("\nGenerating sample text...")
    generated_text = generate_text(final_model, start_string="hello ", 
                                 char2idx=char2idx, idx2char=idx2char, 
                                 num_generate=100)
    print("Generated text:")
    print(generated_text)

if __name__ == '__main__':
    main()
1.3 Transformer模型及其应用

Transformer模型是一种基于自注意力机制的先进神经网络架构,它摒弃了传统的循环结构,通过自注意力机制能够并行处理序列数据,同时捕捉序列中任意位置之间的关系,极大地提升了处理长序列数据的效率和效果。在自然语言处理领域,Transformer模型取得了突破性进展,尤其在文本生成任务中,能够生成流畅、连贯且富有逻辑的文本内容,广泛应用于机器翻译、文本摘要、问答系统等任务中。

接下来将学习如何使用TensorFlow构建和训练Transformer模型。通过掌握其核心机制和实现方法,你将能够利用这一强大的工具解决复杂的自然语言处理问题,提升模型性能并探索更多应用场景。

Transformer模型构建

构建Transformer模型的基本步骤包括定义模型结构、编译模型和训练模型。以下是一个使用TensorFlow构建Transformer模型的示例:

import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Embedding, Dense, Dropout, LayerNormalization
from tensorflow.keras.layers import MultiHeadAttention, Dropout, LayerNormalization

# 定义 TransformerBlock
class TransformerBlock(tf.keras.layers.Layer):
    def __init__(self, embed_dim, num_heads, ff_dim, rate=0.1):
        super(TransformerBlock, self).__init__()
        self.att = MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim)
        self.ffn = tf.keras.Sequential(
            [Dense(ff_dim, activation="relu"), Dense(embed_dim)]
        )
        self.layernorm1 = LayerNormalization(epsilon=1e-6)
        self.layernorm2 = LayerNormalization(epsilon=1e-6)
        self.dropout1 = Dropout(rate)
        self.dropout2 = Dropout(rate)

    def call(self, inputs, training):
        attn_output = self.att(inputs, inputs)
        attn_output = self.dropout1(attn_output, training=training)
        out1 = self.layernorm1(inputs + attn_output)
        ffn_output = self.ffn(out1)
        ffn_output = self.dropout2(ffn_output, training=training)
        return self.layernorm2(out1 + ffn_output)

# 构建 Transformer 模型
def build_transformer_model(vocab_size, embed_dim, num_heads, ff_dim, max_length, batch_size):
    inputs = tf.keras.Input(shape=(max_length,), batch_size=batch_size)
    x = Embedding(vocab_size, embed_dim)(inputs)
    x = TransformerBlock(embed_dim, num_heads, ff_dim)(x, training=True)
    x = tf.keras.layers.GlobalAveragePooling1D()(x)
    x = Dropout(0.1)(x)
    outputs = Dense(vocab_size, activation="softmax")(x)
    model = Model(inputs=inputs, outputs=outputs)
    return model

# 参数设置
vocab_size = 10000
embed_dim = 64
num_heads = 2
ff_dim = 32
max_length = 10
batch_size = 64

# 构建模型
model = build_transformer_model(vocab_size, embed_dim, num_heads, ff_dim, max_length, batch_size)
model.summary()

Transformer模型训练

训练Transformer模型同样需要定义损失函数和优化器。以下是一个训练Transformer模型的示例:

import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Embedding, Dense, Dropout, LayerNormalization
from tensorflow.keras.layers import MultiHeadAttention
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import numpy as np
import os

# 定义 TransformerBlock
class TransformerBlock(tf.keras.layers.Layer):
    def __init__(self, embed_dim, num_heads, ff_dim, rate=0.1):
        super(TransformerBlock, self).__init__()
        self.att = MultiHeadAttention(num_heads=num_heads, key_dim=embed_dim)
        self.ffn = tf.keras.Sequential(
            [Dense(ff_dim, activation="relu"), Dense(embed_dim)]
        )
        self.layernorm1 = LayerNormalization(epsilon=1e-6)
        self.layernorm2 = LayerNormalization(epsilon=1e-6)
        self.dropout1 = Dropout(rate)
        self.dropout2 = Dropout(rate)

    def call(self, inputs, training):
        attn_output = self.att(inputs, inputs)
        attn_output = self.dropout1(attn_output, training=training)
        out1 = self.layernorm1(inputs + attn_output)
        ffn_output = self.ffn(out1)
        ffn_output = self.dropout2(ffn_output, training=training)
        return self.layernorm2(out1 + ffn_output)

# 构建 Transformer 模型
def build_transformer_model(vocab_size, embed_dim, num_heads, ff_dim, max_length, batch_size):
    inputs = tf.keras.Input(shape=(max_length,), batch_size=batch_size)
    x = Embedding(vocab_size, embed_dim)(inputs)
    x = TransformerBlock(embed_dim, num_heads, ff_dim)(x, training=True)
    x = tf.keras.layers.GlobalAveragePooling1D()(x)
    x = Dropout(0.1)(x)
    outputs = Dense(vocab_size, activation="softmax")(x)
    model = Model(inputs=inputs, outputs=outputs)
    return model

# 训练 Transformer 模型
def train_transformer_model(model, dataset, epochs, checkpoint_prefix):
    model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True))
    for epoch in range(epochs):
        model.fit(dataset, epochs=1)
        model.save_weights(checkpoint_prefix.format(epoch=epoch))

# 数据集准备
# 假设我们已经有一个预处理好的数据集
def prepare_dataset(text, max_length, vocab_size):
    tokenizer = Tokenizer(num_words=vocab_size)
    tokenizer.fit_on_texts([text])
    sequences = tokenizer.texts_to_sequences([text])[0]
    
    # 创建输入和标签
    inputs = []
    labels = []
    for i in range(len(sequences) - max_length):
        inputs.append(sequences[i:i + max_length])
        labels.append(sequences[i + max_length])
    
    inputs = np.array(inputs)
    labels = np.array(labels)
    
    return inputs, labels, tokenizer

# 生成合成文本数据
def generate_synthetic_text():
    text = " ".join(["hello world this is a test" for _ in range(1000)])
    return text

# 主函数
def main():
    # 生成合成文本数据
    text = generate_synthetic_text()
    print("Generated text length:", len(text))
    print("Sample text:", text[:50])
    
    # 准备数据集
    max_length = 10
    vocab_size = 20
    inputs, labels, tokenizer = prepare_dataset(text, max_length, vocab_size)
    print("Vocabulary size:", len(tokenizer.word_index) + 1)
    
    # 构建 Transformer 模型
    embed_dim = 64
    num_heads = 2
    ff_dim = 32
    batch_size = 64
    model = build_transformer_model(vocab_size, embed_dim, num_heads, ff_dim, max_length, batch_size)
    model.summary()
    
    # 创建数据集
    dataset = tf.data.Dataset.from_tensor_slices((inputs, labels)).batch(batch_size)
    
    # 训练模型
    checkpoint_prefix = './training_checkpoints/ckpt_{epoch}.weights.h5'
    os.makedirs(os.path.dirname(checkpoint_prefix), exist_ok=True)
    train_transformer_model(model, dataset, epochs=10, checkpoint_prefix=checkpoint_prefix)

if __name__ == '__main__':
    main()

您可能感兴趣的与本文相关的镜像

Qwen3-8B

Qwen3-8B

文本生成
Qwen3

Qwen3 是 Qwen 系列中的最新一代大型语言模型,提供了一整套密集型和专家混合(MoE)模型。基于广泛的训练,Qwen3 在推理、指令执行、代理能力和多语言支持方面取得了突破性进展

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值