如何让电脑学会自己玩游戏

如何让电脑学会自己玩游戏

所用技术: 强化学习 -> Q_learning

可以解决问题的示例:

  1. 在计算机只知道它的动作只有上下左右复制粘贴这六个动作的情况下 学会如何将上一行的文字复制到输出框
  2. 走一维, 二维或三维迷宫, 或者在有陷阱,有奖励的情况下. 获得最大收益或减少成本.
  3. 让计算机玩赌博游戏. 比如猜轮盘转出来的数字,猜对有奖励, 或者选择离开赌桌. 最长期的收益则是计算机选择离开赌桌.

该技术可玩游戏类型的限制:

可玩: 状态有限, 动作有限. (其中一个 精确的解.)

不可玩: 状态无限 或 动作无限. (其中一个 近似的解.)

走迷宫实例参考:走迷宫

游戏名: 寻宝者找宝藏

游戏环境说明:

—O————T

O 代表寻宝者的所在游戏中的位置

代表路径

T 代表宝藏的位置

O 可执行的动作只有

智能体只知道:

它找到宝藏就是最大化收益

它会的动作只有

它可随机出现在整个地图上的任何位置, 并试图找到宝藏

class Game_env():
    def get_env_feedback(self, state, action):
        ...
        # 输入给环境当前的状态 和 需要执行的动作
        # 返回下一个状态 和 下一个状态给的奖励
        # 例如输入: ---O-T  状态为:3  动作为: right
        # 那么输出: ----OT  状态为:4  奖励为: 0

    def update_env(self, state, round, step_counter):
        ...
        # 根据状态更新当前环境,并可视化.
        # 输入为 state=3
        # 输出为 可视化当前状态 终端显示: ---O-T  Treasure 宝物,财富.等意思...
        # round 和 step_counter 用于记录和显示 当前的回合数,和完成一回合游戏所使用的步数.可不使用

class Play_game():
    def build_q_table(self, n_states, actions):
        ...
        # 创建q表 用于指导智能体如何玩游戏
        # state		left  right
		#   0   	0.0    0.0
        #   1   	0.0    0.0
        #   2   	0.0    0.0
        #   3   	0.0    0.0
        #   4   	0.0    0.0
        # 这里可以写成活的q表 判断如果没有此状态则添加.
        # 这里可以扩展到 二维的迷宫游戏或其它 状态有限 动作有限 的游戏
		# state    left  	right  down   up
		# 	0   		0.0    0.0   0.0  	0.0
		# 	1   		0.0    0.0   0.0  	0.0
		# 	2   		0.0    0.0   0.0  	0.0
		# 	3   		0.0    0.0   0.0  	0.0
		# 	4   		0.0    0.0   0.0  	0.0


    def choose_action(self, state):
        ...
        # 根据贪婪率选择随机动作或最大收益动作(电脑自动玩游戏)
        # 也可玩家手动指导智能体玩游戏只需将选择动作的代码改为键盘输入即可(人工指导智能体玩游戏)
        # 输入当前状态 例如: ---O-T  状态为: 3
        # 返回输出动作 例如: left 或者 right


class Train():
    def learning_round(self):
        ...
        # 设置每个回合配置 如下:
        # 1. 初始状态 置零或随机
        # 2. 游戏状态 置为未完成
        # 3. 游戏进行步数 置零
        # 4. 游戏环境初始化
        # 开始学习q表

    def learning_steps(self, state, is_terminated, round, step_count):
        ...
        # 整个游戏初始化后就可以开始玩了.
        # 无限死循环 或者 玩多少步后强制退出都行
        # 1. 选择一个动作 -> 得到一个动作
        # 2. 获得环境的反馈 -> 得到 下一个状态 和 奖励
        # 3. 得到q真实的值 -> 当前的状态 和 选择的动作 确定q真实的值
        # 4. 得到q估计的值 -> 下一步动作的奖励 + 远见 * 下一个状态的所有动作值中的最大值
        # 5. 更新q表的值 -> 学习率 * (q估计 - q现实)
        # 6. 更新当前的状态 -> 当前状态为选择动作后的下一个状态
        # 7. 更新当前的环境
        # 8. 当前回合步数统计, 可省略.
        # 进入下一个回合, 重置游戏各项参数.重新开始玩.
        
        # state		left  right
		#   0   	0.0    0.0
        #   1   	0.0    0.0
        #   2   	0.0    0.0
        #   3   	0.0    0.0
        #   4   	0.0    0.0

更新Q表:

更新后的值 = 更新前的值 + 学习率 * (奖励 + 远见 * q估计值 - q现实值)

Q ( s t , a t ) ← Q ( s t , a t ) + α ⋅ ( r t + γ ⋅ m a x Q ( s t + 1 , a ) − Q ( s t , a t ) ) Q\left (s_{t}, a_{t}\right) \leftarrow Q\left (s_{t}, a_{t} \right)+\alpha \cdot \left(r_{t} +\gamma \cdot maxQ \left (s_{t+1},a \right)-Q \left (s_{t}, a_{t} \right) \right) Q(st,at)Q(st,at)+α(rt+γmaxQ(st+1,a)Q(st,at))

所有代码

import time
import pandas as pd
import numpy as np


class Game_env():
    def __init__(self, N_STATES=5, FRESH_TIME=0.3):
        self.N_STATES = N_STATES   # the length of the 1 dimensional world  状态长度
        self.FRESH_TIME = FRESH_TIME    # fresh time for one move

    def get_env_feedback(self, state, action):
        if action == 'right':    # move right
            if state == self.N_STATES - 1:   # terminate 0 start
                next_state = 'terminal'
                reward = 1
            else:
                next_state = state + 1
                reward = 0
        else:   # move left
            reward = 0
            if state == 0:
                next_state = state  # reach the wall
            else:
                next_state = state - 1
        return next_state, reward

    def update_env(self, state, round, step_counter):
        env_list = ['-']*(self.N_STATES) + ['T']   # '-----T' our environment
        if state == 'terminal':
            interaction = 'Round: %s     Total_move_steps: %s' % (round+1, step_counter)
            print('\r{}'.format(interaction), end='')
            time.sleep(3)
            print('\r                                ', end='')
        else:
            env_list[state] = 'o'
            interaction = ''.join(env_list)
            print('\r{}'.format(interaction), end='')
            time.sleep(self.FRESH_TIME)


class Play_game():
    def __init__(self, N_STATES=5):
        self.N_STATES = N_STATES   # the length of the 1 dimensional world
        self.ACTIONS = ['left', 'right']  # available actions
        self.EPSILON = 0.9  # greedy 有多大概率选择最优动作
        self.q_table = self.build_q_table(self.N_STATES, self.ACTIONS)

    def build_q_table(self, n_states, actions):
        table = pd.DataFrame(np.zeros((n_states, len(actions))), columns=actions, )
        print("\n init q_table: \n", table)
        return table

    def choose_action(self, state):
        state_actions = self.q_table.iloc[state, :]
        if (np.random.uniform() > self.EPSILON) or ((state_actions == 0).all()):
            action_name = np.random.choice(self.ACTIONS)
        else:   # act greedy
            action_name = state_actions.idxmax()
        return action_name


class Train():
    def __init__(self, learn_round=13):
        N_STATES = 5
        self.game_env = Game_env(N_STATES)
        self.play = Play_game(N_STATES)
        self.learn_round = learn_round
        self.ALPHA = 0.1  # learning rate
        self.GAMMA = 0.9  # discount factor # 远见

    def learning_round(self):
        for round in range(self.learn_round):
            state = 0
            is_terminated = False
            step_count = 0
            self.game_env.update_env(state, round, step_count)
            self.learning_steps(state, is_terminated, round, step_count)
            # print("\n" + "=" * 20 + "\n q_table round: {}\n".format(round + 1), self.play.q_table)
        return self.play.q_table

    def learning_steps(self, state, is_terminated, round, step_count):
        while not is_terminated:
            action = self.play.choose_action(state)
            next_state, reward = self.game_env.get_env_feedback(state, action)
            q_predict = self.play.q_table.loc[state, action]
            if next_state != 'terminal':
                q_target = reward + self.GAMMA * self.play.q_table.iloc[next_state, :].max()  
            else:
                q_target = reward  # next state is terminal
                is_terminated = True  # terminate this episode

            self.play.q_table.loc[state, action] += self.ALPHA * (q_target - q_predict)  # update
            state = next_state  # move to next state

            self.game_env.update_env(state, round, step_count + 1)
            step_count += 1


if __name__ == '__main__':
    pass
    # # env show
    # game_env = Game_env()
    # action = "left"
    # next_state, reward = game_env.get_env_feedback(state=4, action=action)
    # print("下一个状态:{}\n下一个状态所给予的奖励:{}".format(next_state, reward))
    # game_env.update_env(next_state, round=1, step_counter=10)

    # # play show
    # play = Play_game()
    # action = play.choose_action(state=4)
    # print("选择的动作名字:", action)

    # # learning
    # agent = Train()
    # learn_result = agent.learning_round()
    # print("\n 最后保存的q_table", learn_result)

你可能感兴趣的:(AI相关概念原理,算法与数据结构)