[AI趣事]让AI成为"文学创作大师":生成式网络的创作魔法 5-17 终极篇

AI摘要
本文介绍了生成式RNN从文本理解到创作的转变,重点讲解了RNN的四种工作模式、字符级生成方法、LSTM模型训练及温度参数控制生成多样性。通过代码示例展示了从数据处理到模型部署的完整流程,并探讨了智能写作、代码生成等实际应用。

嗨,各位AI探索者!

还记得小时候玩的”接龙游戏”吗?一个人说”从前有座山”,下一个人接”山上有座庙”,就这样一句接一句编故事。今天我们要教AI玩这个游戏,而且它比我们玩得还要好!

🎭 从”理解”到”创作”的华丽转身

之前我们做了什么?

# 之前的AI:只会"看"文章分类
input_text = "苹果公司股价大涨"
ai_classifier = "这是财经新闻!"  # 只会判断,不会创作

现在AI能做什么?

# 现在的AI:会"写"文章
prompt = "苹果公司股价"
ai_generator = "苹果公司股价大涨,投资者纷纷看好其新产品发布会带来的利好消息..."
# 能续写,能创作!

就像从”只会读书”的学霸变成了”能写小说”的作家!

🎯 RNN的四种”创作模式”

[AI趣事]RNN模式

图:RNN的四种工作模式,展示不同的输入输出组合

1. One-to-One:传统翻译官

# 一个输入,一个输出
image = "一张猫的照片"
result = "这是一只猫"  # 图像分类

2. One-to-Many:故事创作家

# 一个灵感,一篇文章
seed = "科技"
story = ["科", "技", "改", "变", "生", "活", "..."]  # 展开成完整故事

3. Many-to-One:总结大师

# 一篇文章,一个观点
long_article = ["今天", "天气", "很好", "..."]
summary = "天气报告"  # 就是我们之前做的分类

4. Many-to-Many:翻译专家

# 中文转英文
chinese = ["我", "爱", "编程"]
english = ["I", "love", "programming"]

🎨 字符级创作:从字母开始的艺术

为什么从字符开始?

想象AI是个刚学写字的小朋友:

# 词级生成:需要知道10万个词汇
word_vocab = ["苹果", "香蕉", "葡萄", ...]  # 词汇量巨大

# 字符级生成:只需要26个字母+标点
char_vocab = ['a', 'b', 'c', ..., 'z', '.', '!', '?']  # 简单很多!

构建字符词典

import torch
import collections

def build_char_vocab(texts):
    """构建字符级词典"""
    counter = collections.Counter()

    # 统计所有字符出现频率
    for text in texts:
        counter.update(list(text))  # 按字符分割

    # 构建词典
    vocab = {char: idx for idx, char in enumerate(counter.keys())}
    vocab['<eos>'] = len(vocab)  # 结束标记

    return vocab

# 示例
texts = ["Hello world!", "AI is amazing!"]
char_vocab = build_char_vocab(texts)
print(f"字符词典大小: {len(char_vocab)}")
print(f"'H'的编码: {char_vocab['H']}")

🏗️ 生成式RNN的训练秘籍

训练数据的制作

[AI趣事]让AI成为"文学创作大师":生成式网络的创作魔法 5-17 终极篇

图:以”HELLO”为例展示RNN如何逐字符生成文本

def create_training_data(text, seq_length=10):
    """
    创建训练用的输入-输出对
    例如:"HELLO WORLD" → 
    输入:["H","E","L","L","O"," ","W","O","R","L"]
    输出:["E","L","L","O"," ","W","O","R","L","D"]
    """
    inputs = []
    outputs = []

    for i in range(len(text) - seq_length):
        # 输入:当前位置开始的序列
        input_seq = text[i:i + seq_length]
        # 输出:向后偏移一位的序列
        output_seq = text[i + 1:i + seq_length + 1]

        inputs.append(input_seq)
        outputs.append(output_seq)

    return inputs, outputs

# 示例
text = "Hello, AI world!"
inputs, outputs = create_training_data(text, 5)
print("训练样本:")
for inp, out in zip(inputs[:3], outputs[:3]):
    print(f"输入: '{inp}' → 输出: '{out}'")

LSTM生成器模型

class LSTMGenerator(torch.nn.Module):
    def __init__(self, vocab_size, hidden_dim=128, num_layers=2):
        super().__init__()
        self.vocab_size = vocab_size
        self.hidden_dim = hidden_dim
        self.num_layers = num_layers

        # 多层LSTM
        self.lstm = torch.nn.LSTM(
            vocab_size, hidden_dim, 
            num_layers=num_layers,
            batch_first=True,
            dropout=0.2
        )

        # 输出层:隐藏状态 → 字符概率
        self.output = torch.nn.Linear(hidden_dim, vocab_size)

    def forward(self, x, hidden=None):
        # 字符ID → one-hot编码
        x = torch.nn.functional.one_hot(x, self.vocab_size).float()

        # LSTM处理
        lstm_out, hidden = self.lstm(x, hidden)

        # 输出概率分布
        output = self.output(lstm_out)

        return output, hidden

# 创建模型
vocab_size = len(char_vocab)
model = LSTMGenerator(vocab_size, hidden_dim=256, num_layers=3)
print(f"模型参数数量: {sum(p.numel() for p in model.parameters())}")

🎲 “硬”生成 vs “软”生成

硬生成:完美主义者

def generate_hard(model, start_text, length=100):
    """
    硬生成:总是选择概率最高的字符
    """
    model.eval()
    chars = list(start_text)
    hidden = None

    # 处理起始文本
    for char in start_text:
        char_tensor = torch.tensor([[char_vocab[char]]])
        output, hidden = model(char_tensor, hidden)

    # 生成新字符
    for _ in range(length):
        # 选择概率最高的字符
        next_char_idx = torch.argmax(output[0, -1]).item()
        next_char = idx_to_char[next_char_idx]
        chars.append(next_char)

        # 继续生成
        char_tensor = torch.tensor([[next_char_idx]])
        output, hidden = model(char_tensor, hidden)

    return ''.join(chars)

# 硬生成示例
generated_text = generate_hard(model, "Today is", 50)
print(f"硬生成: {generated_text}")

软生成:艺术创作家

def generate_soft(model, start_text, length=100, temperature=1.0):
    """
    软生成:根据概率分布随机采样
    temperature控制随机性
    """
    model.eval()
    chars = list(start_text)
    hidden = None

    # 处理起始文本
    for char in start_text:
        char_tensor = torch.tensor([[char_vocab[char]]])
        output, hidden = model(char_tensor, hidden)

    # 生成新字符
    for _ in range(length):
        # 应用温度参数
        logits = output[0, -1] / temperature
        probs = torch.softmax(logits, dim=0)

        # 多项式采样
        next_char_idx = torch.multinomial(probs, 1).item()
        next_char = idx_to_char[next_char_idx]
        chars.append(next_char)

        char_tensor = torch.tensor([[next_char_idx]])
        output, hidden = model(char_tensor, hidden)

    return ''.join(chars)

# 不同温度的效果
temperatures = [0.3, 0.8, 1.0, 1.5, 2.0]
for temp in temperatures:
    text = generate_soft(model, "AI is", 30, temperature=temp)
    print(f"温度{temp}: {text}")

温度参数的魔法

# 温度 = 0.1: 保守派
"AI is a powerful tool for solving complex problems..."
# 几乎总是选最可能的字符,文本很规整但可能重复

# 温度 = 1.0: 平衡派  
"AI is amazing and can help us in many ways..."
# 平衡的随机性,既有逻辑又有创意

# 温度 = 2.0: 疯狂派
"AI is xqz!@# random text here..."
# 高度随机,可能产生无意义文本

🚀 完整训练流程

def train_generator(model, train_data, epochs=10):
    """完整的生成器训练流程"""
    optimizer = torch.optim.Adam(model.parameters(), lr=0.002)
    criterion = torch.nn.CrossEntropyLoss()

    for epoch in range(epochs):
        model.train()
        total_loss = 0

        for batch_idx, (inputs, targets) in enumerate(train_data):
            optimizer.zero_grad()

            # 前向传播
            outputs, _ = model(inputs)

            # 计算损失
            loss = criterion(
                outputs.view(-1, vocab_size),
                targets.view(-1)
            )

            # 反向传播
            loss.backward()

            # 梯度裁剪,防止梯度爆炸
            torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)

            optimizer.step()
            total_loss += loss.item()

            # 每1000步输出一次生成样本
            if batch_idx % 1000 == 0:
                sample_text = generate_soft(model, "Today", 50)
                print(f"Epoch {epoch}, Step {batch_idx}: {sample_text}")

        avg_loss = total_loss / len(train_data)
        print(f"Epoch {epoch}: Average Loss = {avg_loss:.4f}")

# 训练模型
train_generator(model, train_loader, epochs=20)

🔧 高级优化技巧

1. 数据预处理优化

class TextDataset(torch.utils.data.Dataset):
    def __init__(self, texts, vocab, seq_length=100):
        self.vocab = vocab
        self.seq_length = seq_length

        # 将所有文本合并成一个大字符串
        self.text = '\n'.join(texts)
        self.chars = [vocab[c] for c in self.text if c in vocab]

    def __len__(self):
        return len(self.chars) - self.seq_length

    def __getitem__(self, idx):
        # 返回输入序列和目标序列
        input_seq = torch.tensor(self.chars[idx:idx + self.seq_length])
        target_seq = torch.tensor(self.chars[idx + 1:idx + self.seq_length + 1])
        return input_seq, target_seq

# 使用数据集
dataset = TextDataset(train_texts, char_vocab, seq_length=50)
dataloader = torch.utils.data.DataLoader(dataset, batch_size=32, shuffle=True)

2. 学习率调度

# 学习率随训练动态调整
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(
    optimizer, 'min', patience=3, factor=0.5
)

# 在训练循环中使用
for epoch in range(epochs):
    # ... 训练代码 ...
    scheduler.step(avg_loss)  # 根据损失调整学习率

📊 生成质量评估

def evaluate_generation_quality(model, test_prompts):
    """评估生成文本质量"""
    results = []

    for prompt in test_prompts:
        # 生成多个版本
        versions = []
        for temp in [0.7, 1.0, 1.3]:
            text = generate_soft(model, prompt, 100, temperature=temp)
            versions.append(text)

        results.append({
            'prompt': prompt,
            'conservative': versions[0],   # 保守版本
            'balanced': versions[1],       # 平衡版本  
            'creative': versions[2]        # 创意版本
        })

    return results

# 测试生成质量
test_prompts = ["Once upon a time", "In the future", "Scientists discovered"]
quality_results = evaluate_generation_quality(model, test_prompts)

for result in quality_results:
    print(f"Prompt: {result['prompt']}")
    print(f"Conservative: {result['conservative'][:50]}...")
    print(f"Creative: {result['creative'][:50]}...")
    print("-" * 50)

🔧 部署优化

Python环境配置

# 按你的偏好配置
import pymysql
pymysql.install_as_MySQLdb()

# 生成式模型推荐配置
"""
torch>=1.9.0
transformers>=4.0.0  # 如果要用预训练模型
numpy>=1.21.0
"""

阿里云服务器部署

# 在你的Linux服务器(宝塔面板+Apache)
pip install torch transformers flask

# 模型服务化部署
# 简单的Flask API
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/generate', methods=['POST'])
def generate_text():
    data = request.json
    prompt = data.get('prompt', 'Hello')
    length = data.get('length', 100)
    temperature = data.get('temperature', 1.0)

    generated_text = generate_soft(model, prompt, length, temperature)

    return jsonify({
        'prompt': prompt,
        'generated_text': generated_text,
        'parameters': {
            'length': length,
            'temperature': temperature
        }
    })

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Golang数据处理脚本

// 大规模文本预处理和结果导出
package main

import (
    "encoding/json"
    "bufio"
    "os"
)

type GenerationResult struct {
    Prompt     string  `json:"prompt"`
    Generated  string  `json:"generated"`
    Temperature float64 `json:"temperature"`
    Timestamp  string  `json:"timestamp"`
}

func exportGenerations(results []GenerationResult, filename string) error {
    file, err := os.Create(filename)
    if err != nil {
        return err
    }
    defer file.Close()

    encoder := json.NewEncoder(file)
    for _, result := range results {
        encoder.Encode(result)
    }

    return nil
}

🎯 实际应用场景

1. 智能写作助手

def writing_assistant(prompt, style="formal"):
    """智能写作助手"""
    # 根据风格调整温度
    temp_map = {
        "formal": 0.7,      # 正式文档
        "creative": 1.2,    # 创意写作
        "technical": 0.5    # 技术文档
    }

    temperature = temp_map.get(style, 1.0)
    return generate_soft(model, prompt, 200, temperature)

# 示例使用
business_email = writing_assistant("Dear Sir/Madam,", "formal")
creative_story = writing_assistant("In a world where", "creative")

2. 代码生成助手

# 可以训练专门的代码生成模型
def code_generator(prompt, language="python"):
    """代码生成助手"""
    full_prompt = f"# {language} code\n{prompt}\n"
    return generate_soft(code_model, full_prompt, 150, temperature=0.3)

# 示例
python_code = code_generator("def calculate_fibonacci(n):")

🎉 今日收获

  • 生成式RNN:从理解文本到创作文本的飞跃
  • 四种模式:一对一、一对多、多对一、多对多
  • 字符级生成:从最基础的字符开始创作
  • 温度控制:在保守和创意之间找平衡
  • 实战技巧:数据处理、训练优化、质量评估

🔮 下期预告

下次我们将进入Transformer的时代!

想知道GPT、BERT这些明星模型的工作原理吗?注意力机制如何让AI”专注”理解语言?敬请期待下一个系列的开篇!

觉得有用记得点赞分享!想看AI写诗、编程的小伙伴欢迎评论区交流~

[AI趣事]RNN推理生成图

图:生成阶段的RNN工作流程,展示如何从初始提示逐步生成完整文本

#AI学习 #生成式AI #RNN #LSTM #文本生成 #深度学习 #机器学习

本作品采用《CC 协议》,转载必须注明作者和本文链接
• 15年技术深耕:理论扎实 + 实战丰富,教学经验让复杂技术变简单 • 8年企业历练:不仅懂技术,更懂业务落地与项目实操 • 全栈服务力:技术培训 | 软件定制开发 | AI智能化升级 关注「上海PHP自学中心」获取实战干货
wangchunbo
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
啥活都干 @ 一人企业
文章
352
粉丝
365
喜欢
581
收藏
1152
排名:58
访问:12.8 万
私信
所有博文
社区赞助商