基于q_learning的flappy bird AI

news/2024/10/30 15:31:38/

基于q_learning的flappy bird AI

思路来自于这篇文章:机器学习玩转Flappy Bird全书:六大“流派”从原理到代码

有两种思路,一种是单步更新q values,一种是全局更新q values。单步更新就是最基础的q learning算法,在agent每产生一个action之后,根据state、action以及next state更新。全局更新是Flappy Bird Bot using Reinforcement Learning in Python这个作者的想法。

我用python实现了单步更新,但是在训练次数达到几百上千次后,发散了。

全局更新基本上属于将Flappy Bird Bot using Reinforcement Learning in Python的python代码用pandas重写了一下。区别之处可能就在于我没有先去生成一个全零的q矩阵。而是在每次碰到新的状态后再写入q矩阵中。最后的状态数量更少,也就是说明初始化的q阵中存在一些永远也用不上的状态。

作者的代码我跑出来的结果:
这里写图片描述
我的代码在 10×10 10 × 10 的网格下的结果:
这里写图片描述
5×5 5 × 5 的网格下的结果:
这里写图片描述
收敛速度变慢的情况下没有取得更好的成绩,可能是参数选取不当。以后有时间再调整参数跑一次。
算法的代码如下:

# coding: utf-8
import numpy as np
import pandas as pdclass Bot(object):def __init__(self, rl=0.7, discount=1.0, greedy=1.0):self.rl = rl  # alphaself.discount = discount  # gammaself.greedy = greedy  # epsilonself.reward = {'living': 1, 'dead': -1000}self.actions = ['0', '1']  # 1 代表clip, 0代表不动self.round = 0  # 玩的局数self.dump_num = 25  # 每dump_num局向csv存储一次q_valuesself.grid_size = 10  # 状态分割大小self.last_state = 'start_state' self.last_action = '0'self.track = []  # 鸟从开始到死亡的所有状态和行为self.q_values = Noneself.load_q_values()self.scores = Noneself.load_score()# choose actiondef choose_action(self, x_coord, y_coord, vel):state = self.add_state(x_coord, y_coord, vel)if np.random.uniform() > self.greedy:action = np.random.choice(self.actions)else:state_actions = self.q_values.loc[state, :]# state_actions = state_actions.reindex(np.random.permutation(state_actions.index)) # 如果权重一样,随机选择# 如果权重一样,选择不跳state_actions = state_actions.astype('int')# print(state_actions)action = state_actions.idxmax()self.track.append([self.last_state, self.last_action, state])self.last_state = stateself.last_action = actionreturn int(action)# 从csv文件中取出q表def load_q_values(self):self.q_values = pd.read_csv('qvalues.csv', index_col=0)# 将q表存入csv文件def dump_q_values(self):if self.round % self.dump_num == 0:self.q_values.to_csv('qvalues.csv')print('Q-values updated on local file.')# 添加状态def add_state(self, x_coord, y_coord, vel):state = self.dif2state(x_coord, y_coord, vel)if state not in self.q_values.index:self.q_values = self.q_values.append(pd.Series([0] * len(self.actions),index=self.q_values.columns,name=state))return state# 将x_coord, y_coord, vel转换成statedef dif2state(self, x_coord, y_coord, vel):if x_coord < 140:x_coord = int(x_coord) - int(x_coord) % self.grid_sizeelse:x_coord = int(x_coord) - int(x_coord) % 70if y_coord < 180:y_coord = int(y_coord) - int(y_coord) % self.grid_sizeelse:y_coord = int(y_coord) - int(y_coord) % 60return str(x_coord) + '_' + str(y_coord) + '_' + str(vel)def update_q_values(self, score):rev_track = list(reversed(self.track))high_dead_flag = True if int(rev_track[0][2].split('_')[1]) > 120 else Falseflag = 1for step in rev_track:if step[0] == 'start_state':continuestate = step[0]action = step[1]next_state = step[2]# print('state:{};action:{}'.format(state, action))# print(self.q_values.loc[state, str(action)])q_predict = self.q_values.loc[state, str(action)]# print(type(q_predict))if flag == 1 or flag == 2:q_target = self.reward['dead'] + self.discount * self.q_values.loc[next_state, :].max()elif high_dead_flag and int(action):q_target = self.reward['dead'] + self.discount * self.q_values.loc[next_state, :].max()high_dead_flag = Falseelse:q_target = self.reward['living'] + self.discount * self.q_values.loc[next_state, :].max()self.q_values.loc[state, action] = q_predict + self.rl * (q_target - q_predict)flag += 1self.round += 1# print('q-val: {}'.format(self.round))self.dump_q_values()self.add_score(score)self.track = []def add_score(self, score):self.scores.loc[self.scores.shape[0]] = scoreself.dump_score()def load_score(self):self.scores = pd.read_csv('scores.csv', index_col=0)# print(self.scores)def dump_score(self):# print('score: {}'.format(self.round))if self.round % self.dump_num == 0:self.scores.to_csv('scores.csv')print('scores updated on local file.')if __name__ == '__main__':bot = Bot()bot.dump_q_values()

学习过程中碰到的好的博客:
A Painless Q-learning Tutorial (一个 Q-learning 算法的简明教程)


http://www.ppmy.cn/news/155019.html

相关文章

华为HCIP RS题库221 171-180题

Q171 OSPF 划分区域的边界在路由器上。 A.TRUE B.FALSE Answer:A Q172 在 IS-IS 的广播网络中&#xff0c;Level-2 路由器使用哪个组播 MAC 地址作为发送 IIH 的目的地址&#xff1f; A.0180-c200-0014 B.0180-c200-0016 C.0180-C200-0015 D.0100-5E00-0002 Answer: C 解析&a…

BMP180气压传感器波动过大的解决方案

BMP180由于其价格原因&#xff0c;静止状态气压数值波动挺大的&#xff0c;就是用最高精度误差也是不小。针对这个误差大的问题&#xff0c;我一直倾向于使用数学方式来进行补偿。 个人的解决方案如下&#xff1a; 使用一阶卡尔曼滤波来对得到的数据进行滤波&#xff0c;以尽…

EQ均衡器中的G 、Q、FC与截止频率知识

最近在一个项目中&#xff0c;与客户的声学工程师关于EQ频响测试有过疑问&#xff0c;也顺便复习了一下关于EQ调试过程中一些参数的意义。 起因如下&#xff0c;一般在TV产品中&#xff0c;声学会调试两组PEQ参数应对不同的场景&#xff0c;桌面模式和壁挂模式&#xff0c;顾名…

RK3326 android10.0(Q) 横屏方案修改

开机logo横屏 U-boot logo 显示的两张图片是 kernel 根目录下的 logo.bmp 和 logo_kernel.bmp&#xff0c;如果 需要更换&#xff0c;用同名的**横屏 bmp **替换掉&#xff0c;重新编译 kernel 附&#xff1a;不一定要两张图片&#xff0c;可以只要一张&#xff0c;如果只有一…

【强化学习】噪声深度Q网络(Noisy DQN)求解倒立摆问题 + Pytorch代码实战

文章目录 一、倒立摆问题介绍二、噪声深度Q网络简介三、详细资料四、Python代码实战4.1 运行前配置4.2 主要代码4.3 运行结果展示4.4 关于可视化的设置 一、倒立摆问题介绍 Agent 必须在两个动作之间做出决定 - 向左或向右移动推车 - 以使连接到它的杆保持直立。 二、噪声深…

I \ Q信号、IFI \ IFQ信号、差分信号、单端信号知识总结

1. IQ信号&#xff1a; &#xff08;1&#xff09;IQ信号即同相正交信号&#xff0c;I为in-phase&#xff0c;Q为quadrature&#xff0c;与I的相位相差了90度。 &#xff08;2&#xff09;因为信号在传输的时候需要的是单一信道、单一频率&#xff0c;因此在最早的通讯技术中…

CARLA平台+Q-learning的尝试(gym-carla)

接触强化学习大概有半年了&#xff0c;也了解了一些算法&#xff0c;一些简单的算法在gym框架也实现了&#xff0c;那么结合仿真平台Carla该怎么用呢&#xff1f;由于比较熟悉gym框架&#xff0c;就偷个懒先从这个开始写代码。 项目地址&#xff1a;https://github.com/cjy1992…

关于Q格式

2010-12-03 22:36 【转】DSP的Q格式讲解 在应用DSP时&#xff0c;其实硬件一般都问题不大&#xff0c;主要的是软件&#xff0c;是算法&#xff01;下面的关于DSP运算的精华但愿有些价值&#xff01; 一 &#xff24;&#xff33;&#xff30;定点算数运算 1 数的定标 在定点D…