从PyTorch官方的一篇教程说开去(4 - Q-table来源及解决问题实例)

偷个懒,代码来自比很久之前看的书,当时还在用gym,我做了微调以升级到gymnasium当前版本,确保可以正常演示。如果小伙伴或者原作者看到了麻烦提一下,我好备注一下出处。

您的进步和反馈是我最大的动力,小伙伴来个三连呗!共勉。

Bug Brain 可能是最古早的神经网络游戏

不知道大家和人工智能的缘分起点在哪里呢?

犹记得当年的控制与系统课,教授带着口音,讲的兴趣盎然,我却听得云里雾里,主要是不知道传递函数这玩意除了算弹簧摆还能干点啥(还没学模电)。恰好隔壁寝室的兄弟好钻研,顺手推荐了这个小游戏给我,于是在略显简陋的面板上摆弄“神经元”做一些小任务,玩得津津有味。当时神经网络这些也是前沿,但实在不算是什么显学,也就一笑而过。如今故友多年未见,虽彼此过的也都还好,总有一些瞬间会让人颇为想念。这里也分享给大家 - 

Bug Brain Home Page

深度学习,乃至目前的LLM,核心都是(矩阵化了的)神经元。这样一个一个毫不出奇的彼此连结着的存着简单数字的小格子,却能一起完成很多本来需要人工操作的项目,这本身就是一件颇为神异的事情!

本例的情景是,当机器面对着下面这个对人类来说颇为简单的小游戏,它那脑子里都有点啥呢?

答案是,一堆格子(本例是16行4列),如下图 - 

看,这就是AI的大脑!

呃,怎么把图形和格子对应起来呢?我们先把图形转换成一个表格 - 

每个状态(方块)允许四种可能的操作:左移、右移、上移、下移。"0"代表不可能的移动(比如你在左上角,你就不可能向左移动或者向上移动!)现在有4x16=64个格子,当我们设计某种算法,让格子里面的分数,代表对应格子对应走法的最大奖励,我们就获得了这样一个Q-table。通过训练,我们可以确保整个Q-table足够好的匹配当前地图。

话不多说,上代码(详细注释) - 以下是创建并训练合适的Q-table:

import numpy as np
import gymnasium as gym
import random

env = gym.make("FrozenLake-v1")

action_size = env.action_space.n
state_size = env.observation_space.n

qtable = np.zeros((state_size, action_size))

total_episodes = 20000       # Total episodes
learning_rate = 0.7          # Learning rate
max_steps = 99               # Max steps per episode
gamma = 0.95                 # Discounting rate

epsilon = 1.0                 # Exploration rate
max_epsilon = 1.0             # Exploration probability at start
min_epsilon = 0.01            # Minimum exploration probability 
decay_rate = 0.005            # Exponential decay rate for exploration prob

rewards = []

for episode in range(total_episodes):
    # Reset the environment
    state = env.reset()[0]
    step = 0
    done = False
    total_rewards = 0
    
    for step in range(max_steps):
        # 3. Choose an action a in the current world state (s)
        exp_exp_tradeoff = random.uniform(0, 1)
        
        if exp_exp_tradeoff > epsilon:
            action = np.argmax(qtable[state,:])
        else:
            action = env.action_space.sample()            
        
        new_state, reward, done, info , _ = env.step(action)
        qtable[state, action] = qtable[state, action] + learning_rate * (reward + gamma * np.max(qtable[new_state, :]) - qtable[state, action])
        
        total_rewards += reward       
        state = new_state
        if done == True: 
            break
        
    epsilon = min_epsilon + (max_epsilon - min_epsilon)*np.exp(-decay_rate*episode) 
    rewards.append(total_rewards)
    
print ("Score over time: " +  str(sum(rewards)/total_episodes))
print(qtable)

接下来是用训练好的Q-table来指导程序自行玩通关游戏 - 

env = gym.make("FrozenLake-v1",render_mode="human")
num_eval_episodes=10

for episode in range(num_eval_episodes):
    state = env.reset()[0]
    step = 0
    done = False
    print("****************************************************")
    print("EPISODE ", episode)

    for step in range(max_steps):
        
        action = np.argmax(qtable[state,:])
        
        new_state, reward, done, info, _ = env.step(action)
        
        if done:
            env.render()
            if new_state == 15:
                print("We reached our Goal 🏆")
            else:
                print("We fell into a hole ☠️")
            
            print("Number of steps", step)
            
            break
        state = new_state
env.close()

因为脑容量很小,所以训练只需几秒完成,效果还不错,2000次的训练可以确保60%以上的通关率,20000次的训练就超过80% 。小伙伴可以自行尝试哈。

代码还有值得提高的空间 - 

 - 直接render,整个训练过程过于冗长。理想的做法是训练过程不看,演示过程才看;

 - 对于关心的胜率等等问题需要直接提供统计数字;

 - 如果需要改成其他游戏,因为env不同,可能会报错,应输出足够的调试信息;

太晚了,这些比较琐碎也比较重要的小事情,我们下一篇来做哈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值