Atari打砖块游戏简介

球碰到砖块、棒子与底下以外的三边会反弹,落到底下会失去一颗球,把砖块全部消去就可以破关。
始祖是史蒂夫·乔布斯与他的好友沃兹(苹果公司的另一位创始人)于1975年的夏末,花了4天时间设计完成的游戏《乒乓》。同时,美国英宝格公司(en:Atari Games,ja:アタリ (ゲーム))于1976年推出的街机游戏“Breakout”,由该公司在1972年发行的“PONG”(en:PONG,ja:ポン (ゲーム),世界上第一款电子游戏,类似台球)改良而来。相较于其前作,一个人就可以玩与变化丰富这两项特点让Breakout相当卖座,使各家公司竞相模仿。
因为规则简单与游戏性,现在许多移动电话都有内建打砖块游戏,也有许多因特网小游戏版本。打砖块游戏一般不大,甚至用软盘即可容下。
代表作:Breakout
《Breakout》 世界上第一款打砖块游戏,1976年由英宝格公司发行。游戏设计是后来创立苹果电脑的史蒂夫·乔布斯与斯蒂夫·沃兹尼亚克两人,程序设计是Brad Stewart。1978年公司发行第二代的Super Breakout。
Gee Bee:《Gee Bee》 日本Namco公司在1978年推出的该公司第一款街机游戏。合并打砖块与弹珠台游戏的特色。
快打砖块(Arkanoid):《Arkanoid》 日本泰托(Taito)公司在1986年推出的街机游戏,引入电脑控制的敌机与后来一般打砖块游戏常见的加强道具(Powerup Item)等要素。

深度Q学习模型简介

与传统的采用数据驱动,学习优化目标函数,迭代循环不同,强化学习的学习过程重点不在于使用一个可以定量解析的目标函数来优化模型,而是通过设定一个学习代理,称为agent,并设置一个规则明确的互动环境environment,使agent能在环境中通过决策方法policy选择行为action,并且获得越来越多的回报reward,从而训练算法做出最优化的action的过程。由此可见,我们的模型其实就是策略policy的制定方法。通过模型,输出一个行为空间的分布,再通过分布找到最有可能的行为。
这样的训练过程大体上可以分为如下几个步骤,1)初始化模型,环境,和回报。2) 做出第一个行为action,通过action计算下一步的环境,以及这一动作带来的回报。3)在新一步的环境中重复这个迭代过程,每经历N步,计算理想回报和实时回报的损失函数。4)优化模型参数,重置环境和奖励,继续重复上述过程。直至损失函数收敛到合理范围或者环境进入最终状态。
我们假设环境在每次采取动作后的变化,仅仅取决于前一步的环境,以及当前动作这两个因素。这意味着环境不具有长期记忆,例如某一步做出的决策如果会在之后间隔很久的时候对环境产生重大影响,则无法利用该方法。这种过程数学上即为马尔可夫过程(Markov Decision Process)。现实中常见的例子如走迷宫,我们在一个分叉路口的决策(朝哪个方向走)会导致环境的变化,反应为位置的更新。但新的位置只取决于当前位置和当前走的方向,与之前几步毫无关联(即如何来到当前位置不影响下一步的环境)。

BreakoutNoFrameskip-v4 换件搭建

import time
import gym
import matplotlib.pyplot as plt

env = gym.make('BreakoutNoFrameskip-v4')
# env = gym.make('ALE/Breakout-v4')
print("Observation Space: ", env.observation_space)
print("Action Space       ", env.action_space)


obs = env.reset()

for i in range(1000):
    env.render()
    action = env.action_space.sample()
    obs, reward, done, info = env.step(action)
    time.sleep(0.01)
env.close()

(2) 基于深度Q学习模型的打砖块游戏博弈

1.	  import hiddenlayer as hl
2.	import torch
3.	import pandas as pd
4.	import numpy as np
5.	import gym
6.	import time
7.	import PIL.Image as Image
8.	import torch.nn as nn
9.	import os
10.	from warnings import catch_warnings
11.	os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'
12.	import warnings
13.	warnings.filterwarnings("ignore")
14.	torch.set_printoptions(profile="full")
15.	 
16.	class DQBReplayer:
17.	    def __init__(self,capacity):
18.	        self.memory = pd.DataFrame(index=range(capacity),columns=['observation','action','reward','next_observation','done'])
19.	        self.i=0
20.	        self.count=0
21.	        self.capacity=capacity
22.	    def store(self,*args):
23.	 
24.	        self.memory.loc[self.i]=args
25.	        self.i=(self.i+1)%self.capacity
26.	        self.count=min(self.count+1,self.capacity)
27.	    def sample(self,size):
28.	        indics=np.random.choice(self.count,size=size)
29.	        return (np.stack(self.memory.loc[indics,field]) for field in self.memory.columns)#为什么#是第indics行和feild列
30.	 
31.	class DQN_net(nn.Module):
32.	    def __init__(self, ):
33.	        super(DQN_net, self).__init__()
34.	        self.conv= nn.Sequential(
35.	            nn.Conv2d(in_channels=4, out_channels=32, kernel_size=8, stride=4),
36.	            nn.ReLU(),
37.	            nn.Conv2d(in_channels=32, out_channels=64, kernel_size=4, stride=2, ),
38.	            nn.ReLU(),
39.	            nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, ),
40.	            nn.ReLU(),
41.	 
42.	        )
43.	 
44.	        self.classifier = nn.Sequential(
45.	            nn.Linear(3136, 512),
46.	            nn.ReLU(),
47.	            nn.Linear(512, 4),
48.	 
49.	      )
50.	 
51.	 
52.	    def forward(self, x):
53.	        x=self.conv(x)
54.	        x=x.view(x.size(0),-1)
55.	        output=self.classifier(x)
56.	        return output
57.	 
58.	 
59.	class DQN(nn.Module):
60.	    def __init__(self,input_shape,env):
61.	        super(DQN,self).__init__()
62.	        self.replayer_start_size = 100000#十万
63.	        self.upon_times=20
64.	        self.replayer=DQBReplayer(capacity=self.replayer_start_size)
65.	        self.action_n=env.action_space.n
66.	        self.image_stack=input_shape[2]
67.	        self.gamma=0.99
68.	        self.image_shape=(input_shape[0],input_shape[1])
69.	        self.e_net=DQN_net()
70.	        self.t_net =DQN_net()
71.	 
72.	 
73.	        self.learn_step=0
74.	        self.max_learn_step=650000#六十五万
75.	        self.epsilon=1.
76.	        self.start_learn=False
77.	 
78.	        self.canvasl = hl.Canvas()
79.	        self.history = hl.History()
80.	 
81.	    def get_nex_state(self,state=None,observation=None):
82.	        img=Image.fromarray(observation,"RGB")
83.	        img=img.resize(self.image_shape).convert('L')
84.	        img=np.asarray(img.getdata(),dtype=np.uint8,).reshape(img.size[1],img.size[0])
85.	        if state is None:
86.	            next_state = np.array([img,]*self.image_stack)
87.	        else:
88.	            next_state=np.append(state[1:],[img,],axis=0)
89.	        return next_state
90.	    def decide(self,state,step):
91.	        if self.start_learn == False:#前5万步随机选择
92.	            action = np.random.randint(0, 4)
93.	            return action
94.	        else:
95.	            self.epsilon -= 0.0000053
96.	        if step<30:#每局前三十步随机选择,中间30万,以一定概率(1-epsilon)通过神经网络选择,最后30万次以0.99概率通过神经网络选择
97.	            action = np.random.randint(0, 4)
98.	        elif  np.random.random() < max(self.epsilon, 0.0005):
99.	            action=np.random.randint(0,4)
100.	        else:
101.	            state=state/128-1.
102.	 
103.	            y=torch.Tensor(state)
104.	            y = y.float().unsqueeze(0)
105.	            y=y.to(device)
106.	 
107.	            x=self.e_net(y).detach()
108.	            if self.learn_step%2000==0:
109.	                print("q value{}".format(x))
110.	            action = torch.argmax(x).data.item()
111.	        return action
112.	 
113.	 
114.	 
115.	Load_Net=int(input("load or not(if this is ur first time to run, input 0,else 1):"))
116.	 
117.	for j in range(9,15,1):
118.	    # 如果训练到j=n时中断,可以把j的起始值设为n-1再运行,并输入1,接着训练
119.	    sum_reward=0
120.	    device=torch.device("cuda" if torch.cuda.is_available() else"cpu")#
121.	    store_count=0
122.	    env=gym.make("BreakoutDeterministic-v4")
123.	    env.unwrapped
124.	 
125.	    net=DQN([84,84,4],env).to(device)
126.	 
127.	    load_net_path="e_3_data\\part"+str(j)+"\\complete_all_training.pkl"
128.	    save_net_path="e_3_data\\part"+str(j+1)+"\\"
129.	 
130.	    net.t_net.load_state_dict(net.e_net.state_dict())
131.	    if Load_Net==1:
132.	        print("u choose to load old net and the path is:",load_net_path)
133.	        net.e_net = torch.load(load_net_path)
134.	        net.t_net = torch.load(load_net_path)
135.	    max_score=0
136.	    mse = nn.MSELoss()
137.	    opt = torch.optim.RMSprop(net.e_net.parameters(), lr=0.00015) #12/13 lr=0.00015 效果
138.	    if Load_Net == 0:
139.	        Load_Net = 1
140.	    print(net.t_net)
141.	    #i是已经玩过的游戏局数
142.	    for i in range(20000):
143.	        lives=5
144.	        action_list = [0, 0, 0, 0]#用于统计选择四种动作的频率
145.	        if net.learn_step>net.max_learn_step:
146.	            torch.save(net.e_net, save_net_path+"complete_all_training.pkl")
147.	            print("complete_all_training")
148.	            break
149.	        observation = env.reset()
150.	        state=net.get_nex_state(None,observation)
151.	        epoch_reward=0#每局游戏的累计奖励
152.	        if i%net.upon_times==0:
153.	            print("{} times_game".format(i))
154.	        if i%10==0:
155.	            time_start = time.time()  # 开始计时
156.	 
157.	        for step in range(500000):
158.	        #step为一局游戏的步数
159.	            # env.render()  # 环境展示,为节省时间,不展示
160.	            action=net.decide(state,step=step)
161.	            action_list[action]+=1
162.	            observation,r,done,info=env.step(action)
163.	            next_state=net.get_nex_state(state,observation)
164.	            # print(info)
165.	            epoch_reward+=r
166.	            # net.learn(state,action,r,next_state,done)
167.	            dead = info['lives'] < lives
168.	            lives = info['lives']
169.	            r=1*r
170.	            if dead:
171.	                r=-1
172.	            net.replayer.store(state, action, r, next_state, done)
173.	            net.learn_step += 1
174.	            if net.learn_step >=net.replayer_start_size // 2 and net.learn_step % 4 == 0:
175.	                if net.start_learn == False:
176.	                    net.start_learn = True
177.	                    print("start_learn")
178.	                sample_n = 32  # 每批训练32个样本
179.	                states, actions, rewards, next_states, dones = net.replayer.sample(sample_n)
180.	                states = states / 128 - 1.
181.	                next_states = next_states / 128 - 1.
182.	                rewards = torch.Tensor(np.clip(rewards,-1,1)).unsqueeze(1).to(device)
183.	                states = torch.Tensor(states).to(device)
184.	 
185.	                next_states = torch.Tensor(next_states).to(device)
186.	                actions = torch.Tensor(actions).long().unsqueeze(1).to(device)
187.	                dones = torch.Tensor(dones).unsqueeze(1).to(device)
188.	                # print("learn{}".format(states))
189.	                q = net.e_net(states).gather(1, actions)
190.	                q_next = net.t_net(next_states).detach().max(1)[0].reshape(sample_n, 1)
191.	                # 这里会不会有错?
192.	                tq = rewards + net.gamma * (1 - dones) * q_next
193.	                loss = mse(q, tq)
194.	                opt.zero_grad()
195.	                loss.backward()
196.	                opt.step()
197.	                if net.learn_step % (net.upon_times * 5) == 0:
198.	                    net.t_net.load_state_dict(net.e_net.state_dict())
199.	                if net.learn_step % 100 == 0:
200.	                    loss_record = loss.item()
201.	                    a_r = torch.mean(rewards, 0).item()
202.	                    net.history.log((net.learn_step), loss=loss_record,avg_reward=a_r)
203.	                    with net.canvasl:
204.	                        net.canvasl.draw_plot(net.history["loss"])
205.	                        net.canvasl.draw_plot(net.history["avg_reward"])
206.	 
207.	            state = next_state
208.	            if done:
209.	                sum_reward+=epoch_reward
210.	                if epoch_reward > max_score:
211.	                    name = "epsiode_" + str(net.learn_step) + "_reward_" + str(epoch_reward) + ".pkl"
212.	                    torch.save(net.e_net, save_net_path+name)
213.	                    max_score = epoch_reward
214.	                elif i % 1000 == 0:
215.	                    name ="No."+str(i)+".pkl"
216.	                    torch.save(net.e_net, save_net_path + name)
217.	                if i%10==0:
218.	                    time_end = time.time()  # 结束计时
219.	                    print("sum_time {:.2f}s---avg_reward:{:.2f}---epsilon {:.2f}---action_p{}".format(time_end-time_start,sum_reward/(10),net.epsilon,[round(pro/sum(action_list),2) for pro in action_list]))
220.	                    sum_reward=0
221.	                break

结果如下:

打砖块小游戏java代码 打砖块游戏叫什么名字_游戏


打砖块小游戏java代码 打砖块游戏叫什么名字_打砖块小游戏java代码_02


打砖块小游戏java代码 打砖块游戏叫什么名字_游戏_03

出现的问题及解决方法

1. 问题:torch.Tensor和torch.tensor的区别 决:

torch.Tensor(data)是将输入的data转化torch.FloatTensor
torch.tensor(data):(当你未指定dype的类型时)将data转化为torch.FloatTensor、torch.LongTensor、torch.DoubleTensor等类型,转化类型依据于data的类型或者dtype的值。

2. 问题:Cannot call env.step() before calling reset()

解决:定位到这一行实际解决问题的方法应该是在environment.py文件中的def init语句内把self._screen = None改为self._screen = self.env.reset()

总结

智能体通过强化学习,可以知道自己在什么状态下,应该采取什么样的动作使得自身获得最大奖励。由于智能体与环境的交互方式与人类与环境的交互方式类似,可以认为强化学习是一套通用的学习框架,可用来解决通用人工智能的问题。总的来说,强化学习是一门比较高深的技术。可应用领域非常广,需要用到的知识和技术多,数学、计算机基础等。如果能在程序或者系统中使用可使程序/系统更加智能化,用户体验更好。