🌟 完整项目和代码

本教程是 AI 入门 30 天挑战 系列的一部分!


Week 4 第四天:AI 如何学会自主决策!
Q-learning + DQN + 股票交易策略!
每个概念都解释!每行代码都说明白!
预计时间:3-4 小时(含费曼输出练习)


📖 第 1 步:快速复习昨天的内容(30 分钟)

费曼输出 #0:考考你

合上教程,尝试回答:

□ 情感分析和文本分类有什么区别?
□ BERT 为什么比关键词匹配更准确?
□ 如何用情感分析监控股民情绪?
□ 如果论坛突然全是负面评论,说明了什么?
□ 如果用强化学习做交易决策,你会怎么设计?

⏰ 时间:25 分钟

如果能答出 80% 以上,我们开始今天的强化学习之旅!如果不够,花 5 分钟翻一下 Day24 的笔记。


🤔 第 2 步:强化学习到底是什么?(60 分钟)

说人话版本

想象你在训练一只小狗:

传统机器学习(监督学习):
→ 你告诉它:"坐下",然后按着它坐下
→ 给它看正确答案
→ 它照做就给奖励

强化学习:
→ 你说:"坐下"
→ 它尝试各种动作(趴下、打滚、叫...)
→ 有一次不小心坐下了
→ 你马上给零食🍖
→ 它明白了:坐下 = 有吃的
→ 下次就会主动坐下

这就是强化学习!
- 没有标准答案
- 通过试错学习
- 做对了有奖励
- 目标是最大化总奖励
生活中的例子:炒股

新手股民入市:
→ 不知道买什么股票
→ 今天买 A 股,涨了!赚钱了😄
→ 明天买 B 股,跌了!亏钱了😭
→ 后天买 C 股,又涨了!
→ ...

慢慢地,他学会了:
✓ 什么情况下该买入
✓ 什么情况下该卖出
✓ 什么时候该观望

这个过程就是强化学习!
- Agent(智能体)= 股民
- Environment(环境)= 股市
- Action(动作)= 买入/卖出/持有
- Reward(奖励)= 赚钱/亏钱
- State(状态)= 当前持仓、资金、市场情况

强化学习的核心概念

五个关键要素:

1. Agent(智能体)
   = 学习者和决策者
   = 股民、棋手、游戏玩家
   
2. Environment(环境)
   = 外部世界
   = 股市、棋盘、游戏场景
   
3. State(状态)
   = 当前的情况
   = 持仓情况、棋子位置、游戏画面
   
4. Action(动作)
   = 可以做的选择
   = 买入/卖出、走棋、跳跃
   
5. Reward(奖励)
   = 即时反馈
   = 赚钱 (+)、亏钱 (-)、赢棋 (+)、输棋 (-)

目标:
找到最优策略 (Policy)
→ 在每种状态下,选择最佳动作
→ 最大化长期累积奖励

🎯 费曼输出 #1:向小白解释强化学习

任务 1:创造多个比喻

场景 A:向小学生解释

用训练宠物
强化学习 = 训练小狗
Agent = 小狗
Environment = 家里
Action = 坐下、握手、打滚
Reward = 零食

小狗不知道要做什么
→ 尝试各种动作
→ 发现"坐下"有零食
→ 就学会坐下了

场景 B:向股民解释

用炒股实战
强化学习 = 散户炒股
Agent = 你
Environment = A 股市场
Action = 买入/卖出/持有
Reward = 涨停 (+10%)、跌停 (-10%)

你不知道什么时候买卖
→ 凭感觉操作
→ 赚钱的操作记住
→ 亏钱的操作改正
→ 慢慢就成了老股民

场景 C:向家长解释

用教育孩子
强化学习 = 培养孩子
Agent = 孩子
Environment = 家庭 + 学校
Action = 好好学习、玩游戏、做家务
Reward = 表扬、零花钱、批评

孩子不知道什么是对的
→ 尝试不同行为
→ 考得好有奖励
→ 调皮被批评
→ 逐渐形成好习惯

要求: 每个场景都要详细说明

⏰ 时间:20 分钟


💡 卡壳检查点

如果你在解释时卡住了:

□ 我说不清楚强化学习和监督学习的区别
□ 我不知道如何解释"试错"的过程
□ 我只能说"AI 学习",但不能说明白怎么决策

这很正常! 标记下来,继续往下看,然后重新尝试解释!

提示:

  • 监督学习 = 老师教学生(有标准答案)
  • 强化学习 = 自己摸索(没有答案,只有奖励)
  • 试错 = 尝试 → 失败 → 再尝试 → 成功

🔬 第 3 步:Q-learning 详解(70 分钟)

核心思想

Q-learning 是什么?

Q = Quality(质量)
→ 某个动作有多好

想法很简单:
1. 建一个表格 (Q-table)
2. 记录每种状态下,每个动作的价值
3. 通过尝试,不断更新这个表格
4. 最后就知道什么情况下该做什么了

举个例子(炒股):

状态:股价连续下跌 3 天
动作选项:买入、卖出、持有

初始 Q-table(随机值):
买入:0.5
卖出:0.3
持有:0.2

尝试买入 → 股价反弹 → 赚钱了!
更新 Q-table:
买入:0.8 (提高了)

再次遇到同样情况:
→ 查 Q-table
→ 买入的值最大 (0.8)
→ 选择买入!

Q-learning 算法流程

"""
Q-learning 算法步骤:

初始化 Q-table(全 0 或随机)

重复以下步骤直到学会:

1. 观察当前状态 s

2. 选择动作 a
   - 探索 (Exploration): 随机选一个动作
   - 利用 (Exploitation): 选 Q 值最大的动作
   
   为什么要探索?
   → 可能更好的动作还没试过
   → 不能只盯着已知的

3. 执行动作 a,得到奖励 r 和新状态 s'

4. 更新 Q-table:
   Q(s,a) = Q(s,a) + α * [r + γ * max(Q(s')) - Q(s,a)]
   
   解释每一项:
   - α (alpha): 学习率 (0-1)
     → 学多快?1 = 完全相信新经验,0 = 不学习
   
   - γ (gamma): 折扣因子 (0-1)
     → 多看重未来?1 = 只看长远,0 = 只顾眼前
   
   - r: 即时奖励
     → 这次做得怎么样?
   
   - max(Q(s')): 未来最大期望
     → 下一步最多能得多少?

5. 进入新状态 s',继续循环

最后:
Q-table 收敛 → 学会最优策略
"""

完整代码实现

import numpy as np
import matplotlib.pyplot as plt

print("=" * 60)
print("🎮 Q-learning 从零实现 - 股票交易示例")
print("=" * 60)

class StockTradingEnv:
    """简化的股票交易环境"""
    
    def __init__(self, initial_price=100):
        self.initial_price = initial_price
        self.price = initial_price
        self.day = 0
        self.prices = []
        
        # 生成一些模拟股价数据
        np.random.seed(42)
        days = 100
        changes = np.random.randn(days).cumsum() * 2  # 随机游走
        self.all_prices = self.initial_price + changes
        
    def reset(self):
        """重置环境"""
        self.price = self.initial_price
        self.day = 0
        return self._get_state()
    
    def _get_state(self):
        """获取当前状态"""
        # 简化:状态就是当前股价的区间
        if self.price < 90:
            return 0  # 低价区
        elif self.price < 110:
            return 1  # 中价区
        else:
            return 2  # 高价区
    
    def step(self, action, shares=100):
        """
        执行动作
        
        参数:
        action: 0=买入,1=卖出,2=持有
        shares: 交易股数
        
        返回:
        new_state: 新状态
        reward: 奖励
        done: 是否结束
        """
        old_price = self.price
        
        # 进入下一天
        self.day += 1
        if self.day >= len(self.all_prices):
            self.day = len(self.all_prices) - 1
        
        self.price = self.all_prices[self.day]
        price_change = self.price - old_price
        
        # 计算奖励
        if action == 0:  # 买入
            reward = price_change * shares  # 股价上涨赚钱
        elif action == 1:  # 卖出
            reward = -price_change * shares  # 股价下跌赚钱(做空)
        else:  # 持有
            reward = 0
        
        new_state = self._get_state()
        done = self.day >= len(self.all_prices) - 1
        
        return new_state, reward, done

class QLearningAgent:
    """Q-learning 智能体"""
    
    def __init__(self, n_states=3, n_actions=3, alpha=0.1, gamma=0.9, epsilon=0.1):
        """
        参数:
        n_states: 状态数
        n_actions: 动作数
        alpha: 学习率
        gamma: 折扣因子
        epsilon: 探索率(ε-greedy 策略)
        """
        self.n_states = n_states
        self.n_actions = n_actions
        self.alpha = alpha  # 学习率
        self.gamma = gamma  # 折扣因子
        self.epsilon = epsilon  # 探索率
        
        # 初始化 Q-table (状态数 × 动作数)
        self.q_table = np.zeros((n_states, n_actions))
        
        print(f"\n✓ Q-learning Agent 初始化完成")
        print(f"  状态数:{n_states}")
        print(f"  动作数:{n_actions}")
        print(f"  学习率 (α): {alpha}")
        print(f"  折扣因子 (γ): {gamma}")
        print(f"  探索率 (ε): {epsilon}")
    
    def choose_action(self, state):
        """选择动作(ε-greedy 策略)"""
        if np.random.random() < self.epsilon:
            # 探索:随机选择
            return np.random.randint(self.n_actions)
        else:
            # 利用:选择 Q 值最大的动作
            return np.argmax(self.q_table[state])
    
    def update(self, state, action, reward, next_state, done):
        """更新 Q-table"""
        if not done:
            # Q-learning 更新公式
            best_next_action = np.argmax(self.q_table[next_state])
            td_target = reward + self.gamma * self.q_table[next_state][best_next_action]
            td_error = td_target - self.q_table[state][action]
            self.q_table[state][action] += self.alpha * td_error
        else:
            # 终止状态,没有未来
            self.q_table[state][action] += self.alpha * (reward - self.q_table[state][action])
    
    def get_policy(self):
        """获取策略(从 Q-table 提取)"""
        policy = np.argmax(self.q_table, axis=1)
        return policy

# ============================================================================
# 训练过程
# ============================================================================

print("\n" + "=" * 60)
print("【开始训练】Q-learning 股票交易策略")
print("=" * 60)

# 创建环境和智能体
env = StockTradingEnv(initial_price=100)
agent = QLearningAgent(n_states=3, n_actions=3, alpha=0.1, gamma=0.9, epsilon=0.1)

# 训练参数
n_episodes = 1000
max_steps = 50

# 记录奖励历史
rewards_history = []
avg_rewards = []

print(f"\n训练设置:")
print(f"  - 训练轮数:{n_episodes}")
print(f"  - 每轮最大步数:{max_steps}")
print(f"  - 初始探索率:{agent.epsilon}")

print("\n开始训练...\n")

for episode in range(n_episodes):
    state = env.reset()
    total_reward = 0
    
    for step in range(max_steps):
        # 选择动作
        action = agent.choose_action(state)
        
        # 执行动作
        next_state, reward, done = env.step(action)
        
        # 更新 Q-table
        agent.update(state, action, reward, next_state, done)
        
        total_reward += reward
        state = next_state
        
        if done:
            break
    
    rewards_history.append(total_reward)
    
    # 计算移动平均
    if len(rewards_history) >= 10:
        avg_reward = np.mean(rewards_history[-10:])
        avg_rewards.append(avg_reward)
    
    # 显示进度
    if (episode + 1) % 100 == 0:
        avg = np.mean(rewards_history[-100:])
        print(f"Episode {episode+1}/{n_episodes} - 平均奖励:{avg:.2f}")

print("\n✓ 训练完成!")

# ============================================================================
# 可视化结果
# ============================================================================

print("\n" + "=" * 60)
print("【结果可视化】")
print("=" * 60)

# 绘制奖励变化
plt.figure(figsize=(14, 5))

plt.subplot(1, 2, 1)
plt.plot(rewards_history, alpha=0.6, label='单轮奖励')
if len(avg_rewards) > 0:
    plt.plot(range(10, len(rewards_history)+1), avg_rewards, 'r-', linewidth=2, label='10 轮平均')
plt.xlabel('训练轮数')
plt.ylabel('累积奖励')
plt.title('训练过程中的奖励变化')
plt.legend()
plt.grid(True, alpha=0.3)

plt.subplot(1, 2, 2)
plt.imshow(agent.q_table, cmap='Blues', aspect='auto')
plt.colorbar(label='Q 值')
plt.xticks(range(3), ['买入', '卖出', '持有'])
plt.yticks(range(3), ['低价区', '中价区', '高价区'])
plt.title('训练后的 Q-table')

# 在格子中显示数值
for i in range(3):
    for j in range(3):
        plt.text(j, i, f'{agent.q_table[i, j]:.2f}',
                ha='center', va='center', color='black' if agent.q_table[i, j] < 0.5 else 'white')

plt.tight_layout()
plt.show()

# ============================================================================
# 展示学到的策略
# ============================================================================

print("\n" + "=" * 60)
print("【学到的交易策略】")
print("=" * 60)

policy = agent.get_policy()
action_names = ['买入', '卖出', '持有']
state_names = ['低价区 (<90)', '中价区 (90-110)', '高价区 (>110)']

print("\n在不同状态下的最优动作:")
for state in range(3):
    action = policy[state]
    q_values = agent.q_table[state]
    best_q = q_values[action]
    
    emoji = {'买入': '🟢', '卖出': '🔴', '持有': '⚪'}
    
    print(f"\n{state_names[state]}:")
    print(f"  最优动作:{emoji[action_names[action]]} {action_names[action]}")
    print(f"  Q 值:{best_q:.3f}")
    print(f"  所有动作 Q 值:买入={q_values[0]:.3f}, 卖出={q_values[1]:.3f}, 持有={q_values[2]:.3f}")

print("\n💡 策略解读:")
if policy[0] == 0:  # 低价区买入
    print("  ✓ 低价区买入 - 价值投资理念")
if policy[2] == 1:  # 高价区卖出
    print("  ✓ 高价区卖出 - 止盈策略")
if policy[1] == 2:  # 中价区持有
    print("  ✓ 中价区持有 - 观望等待")

print("\n🎊 Q-learning 训练完成!")
print("=" * 60)

# ============================================================================
# 实际应用建议
# ============================================================================

print("\n" + "=" * 60)
print("【6. 实际应用建议】")
print("=" * 60)

print("""
使用场景推荐:

1. 自动化交易:
   ✓ 学习历史交易数据
   ✓ 发现盈利模式
   ✓ 自动执行买卖
   ✓ 24 小时监控市场

2. 游戏 AI:
   ✓ AlphaGo 下围棋
   ✓ Dota2 游戏 AI
   ✓ 超级玛丽通关
   ✓  Atari 游戏大师

3. 机器人控制:
   ✓ 机械臂抓取
   ✓ 自动驾驶
   ✓ 无人机飞行
   ✓ 人形机器人走路

4. 资源调度:
   ✓ 数据中心冷却
   ✓ 交通信号控制
   ✓ 电力网络优化
   ✓ 物流配送路径

技术要点:

✓ 状态空间设计
  - 不能太大(计算不了)
  - 不能太小(信息不足)
  - 可以用函数近似(神经网络)

✓ 奖励函数设计
  - 要及时(延迟奖励难学)
  - 要准确(反映真实目标)
  - 要平衡短期和长期

✓ 探索 vs 利用
  - ε-greedy: 简单有效
  - UCB: 更智能的探索
  - Thompson Sampling: 概率方法

常见问题:

✗ 维度灾难
  → 状态太多,Q-table 存不下
  → 解决:用 DQN(深度 Q 网络)

✗ 奖励稀疏
  → 很久才得到一次奖励
  → 解决:设计中间奖励

✗ 不收敛
  → 学习率太高或太低
  → 调整α、γ、ε参数
""")

print("\n🎉 强化学习入门完成!")
print("=" * 60)

按 Shift + Enter 运行!


🎯 费曼输出 #2:深入理解技术

任务 1:解释技术细节

思考题:

  1. Q-learning 和监督学习的本质区别是什么?
  2. 为什么要平衡探索和利用?
  3. 学习率α和折扣因子γ各起什么作用?
  4. 如果状态空间很大(比如图像),怎么办?

任务 2:设计交易系统

场景:你要用强化学习设计一个完整的股票交易系统

要求:

  1. 定义状态空间(用什么特征表示状态)
  2. 定义动作空间(可以做什么操作)
  3. 设计奖励函数(什么是好什么是坏)
  4. 选择算法(Q-learning 还是 DQN)

⏰ 时间:30 分钟


💡 卡壳检查点

  • 我解释不清探索和利用的矛盾
  • 我说不明白 Q-learning 更新的含义
  • 我不能设计实际的强化学习系统

提示:

  • 探索 = 尝试新东西,利用 = 用已知最好的
  • Q-learning 更新 = 根据新经验调整旧认知
  • 大状态空间 = 用神经网络近似 Q 值(DQN)

💻 第 4 步:DQN 深度强化学习简介(40 分钟)

"""
DQN = Deep Q-Network(深度 Q 网络)

解决的问题:
Q-learning 只能处理小状态空间
→ 状态多了,Q-table 太大存不下
→ 比如围棋:10^170 种状态
→ 比如图像:每个像素都是状态

解决方案:
用神经网络代替 Q-table!

输入:状态(比如游戏画面)
      ↓
   神经网络
      ↓
输出:每个动作的 Q 值

好处:
✓ 可以处理高维状态
✓ 可以泛化到未见过的状态
✓ AlphaGo、Dota2 AI 都用这个

但 DQN 很复杂,需要:
- 经验回放(Experience Replay)
- 目标网络(Target Network)
- 梯度裁剪(Gradient Clipping)

这些留给进阶课程!
"""

🎉 今日费曼总结(30 分钟)⭐

完整的费曼学习流程

第 1 步:回顾今天的内容(5 分钟)

  • 强化学习的基本概念
  • Q-learning 算法原理
  • 股票交易策略学习

第 2 步:合上教程,尝试完整教授(15 分钟)⭐

任务:假装你在给一个完全不懂的人上第二十五堂课

要覆盖:

  1. 强化学习是怎么工作的(用至少 2 个比喻)
  2. Q-learning 的更新公式含义
  3. 演示股票交易策略学习
  4. 讲解实际应用场景

方式:写一篇 800 字左右的文章,或录一段 10-15 分钟的视频

第 3 步:标记卡壳点(5 分钟)

我今天卡壳的地方: □ _________________________________ □ _________________________________

第 4 步:针对性复习(5 分钟)

回到教程中卡壳的地方,重新学习,然后再次尝试解释!


📝 费曼学习笔记模板

╔═══════════════════════════════════════════════════╗
║         Day 25 费曼学习笔记                       ║
╠═══════════════════════════════════════════════════╣
║ 日期:__________                                  ║
║ 学习时长:__________                              ║
╠═══════════════════════════════════════════════════╣
║                                                   ║
║ 1. 我向小白解释了:                               ║
║ _______________________________________________  ║
║                                                   ║
║ 2. 我卡壳的地方:                                 ║
║ □ _____________________________________________  ║
║                                                   ║
║ 3. 我的通俗比喻:                                 ║
║ • 强化学习就像 ______                             ║
║ • Q-table 就像 ______                             ║
║ • 探索 vs 利用就像 ______                         ║
║                                                   ║
╚═══════════════════════════════════════════════════╝

📊 今日总结

✅ 你今天学到了:

  1. 强化学习基础

    • Agent、Environment、State、Action、Reward
    • 试错学习
    • 最大化长期奖励
  2. Q-learning 算法

    • Q-table 构建
    • ε-greedy 策略
    • 贝尔曼方程更新
  3. 实战应用

    • 股票交易策略
    • 可视化分析
    • 策略解读
  4. 费曼输出能力 ⭐

    • 能用比喻解释强化学习
    • 能向小白说明 Q-learning
    • 能完整讲解交易系统

🎁 明日预告

明天你将学习:模型部署和工程化

内容:

  • Flask API 部署
  • ONNX 格式转换
  • 移动端部署
  • 实战:把模型变成 Web 服务

准备好让你的 AI 模型走出实验室,服务真实用户了吗?继续前进!🚀


🔗 相关链接

🌐 项目资源


本教程属于 AI 入门 30 天挑战 系列


🎉 恭喜你完成今天的学习!

💬 互动时间

思考题:今天的知识点中,哪个让你印象最深刻?为什么?

欢迎在评论区分享你的想法或疑问!👇

❤️ 如果有帮助

  • 👍 点赞:让更多人看到这篇教程
  • ⭐ Star GitHub:获取完整代码和项目
  • ➕ 关注专栏:不错过后续更新
  • 🔄 分享给朋友:一起学习进步

明天见!继续 Day 26 的学习~ 🚀


💡 学习建议

如果本篇教程对你有帮助,欢迎:

  1. Star GitHub 项目https://github.com/Lee985-cmd/AI-30-Day-Challenge
  2. 留言交流你的学习困惑

一起学习,一起进步! 🤝

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐