从零使用强化学习训练AI玩儿游戏(9)——使用DQN(Keras+CNN)

做了这么。。。。。终于到达这一步了。

GitHub上源代码​​​​​​​

上一篇我们用简单的全连接神经网络实现了DQN玩儿了一个简单的游戏,今天我们要用一个复杂的神经网络来玩儿一个复杂的游戏,SpaceInvaders-v0,就玩这个游戏吧,看起来很棒的样子,随便选的。

在这个游戏中observaction是一个屏幕RGB的图片,shape是(210,160,3) = 100800个数据正好试一下卷积神经网络,action 6个中4是发送子弹 2、3分别是左右,reward就是你打没打死那个外星人所得到的奖励,就是图片上的分数,reward分别是5,10,15,20,25,30,每往上增加一层的外星人加5分,然后时不时的有一个紫色的外星人出现,打中他加200分,这里可以考虑做不做归一化处理,我这里先不做归一化处理直接使用它的reward。然后我看国外的论文中也有用opencv先做一个图像处理的,我这里也先不做了就用原图。

看来我还是太小看这个神经网络的训练,还有太高估我渣渣电脑的能力了,居然还想不做图像预处理直接跑。。。。。。根本跑不动啊。。。。我还是老老实实加opencv预处理吧,还有opencv比较熟悉。

所以使用这个教程安装opencv,在这个教程中我没有进入Windows的终端,而是进入anaconda prompt进行安装的,要不然找不到pip命令。

做灰度化处理后的效果:

加了opencv处理后还是很慢,但是比之前好多了

接下来还需要继续优化神经网络,让训练的速度变快。

真正遇到大数据做机器学习的时候就知道自己的电脑有多差了。。。。。。。可优化后的学习速度都需要1.1s左右,导致整个游戏完全没法看,所以我开了一个线程来控制是否学习,也就是说关闭学习的时候能从游戏界面中看出学习的成果,但还是太慢了。。。。。。。所以接下来可能在网上租一个服务器,或者去实验室用实验室的服务器来跑一跑看看效果。

接下来看看我搭的神经网络是什么样的,看起来很大的样子,其实说到底也就是四层,前两层是卷积神经网络,配备了pooling减少数据损失,然后加上两层全连接网络,本来这个地方是要放LSTM的,但是我的电脑更跑不动了。。。。。。所以先用全连接。等我找到好的服务器再修改。

       

这个是搭建两个神经网络的代码,Keras搭建的,真的超级方便。(详见注释)

    def _build_net(self):
        # ------------------ 建造估计层 ------------------
        # 因为神经网络在这个地方只是用来输出不同动作对应的Q值,最后的决策是用Q表的选择来做的
        # 所以其实这里的神经网络可以看做是一个线性的,也就是通过不同的输入有不同的输出,而不是确定类别的几个输出
        # 这里我们先按照上一个例子造一个两层每层单个神经元的神经网络
        self.model_eval = Sequential([
            # 输入第一层是一个二维卷积层(100, 80, 1)
            Convolution2D(                              # 就是Conv2D层
                batch_input_shape=(None, self.observation_shape[0], self.observation_shape[1],
                                   self.observation_shape[2]),
                filters=15,                             # 多少个滤波器 卷积核的数目(即输出的维度)
                kernel_size=5,                          # 卷积核的宽度和长度。如为单个整数,则表示在各个空间维度的相同长度。
                strides=1,                              # 每次滑动大小
                padding='same',                         # Padding 的方法也就是过滤后数据xy大小是否和之前的一样
                data_format='channels_last',           # 表示图像通道维的位置,这里rgb图像是最后一维表示通道
            ),
            Activation('relu'),
            # 输出(100, 80, 15)
            # Pooling layer 1 (max pooling) output shape (50, 40, 15)
            MaxPooling2D(
                pool_size=2,                            # 池化窗口大小
                strides=2,                              # 下采样因子
                padding='same',                         # Padding method
                data_format='channels_last',
            ),
            # output(50, 40, 30)
            Convolution2D(30, 5, strides=1, padding='same', data_format='channels_last'),
            Activation('relu'),
            # (10, 8, 30)
            MaxPooling2D(5, 5, 'same', data_format='channels_first'),
            # (10, 8, 30)
            Flatten(),
            # LSTM(
            #     units=1024,
            #     return_sequences=True,  # True: output at all steps. False: output as last step.
            #     stateful=True,          # True: the final state of batch1 is feed into the initial state of batch2
            # ),
            Dense(512),
            Activation('relu'),
            Dense(self.n_actions),
        ])
        # 选择rms优化器,输入学习率参数
        rmsprop = RMSprop(lr=self.lr, rho=0.9, epsilon=1e-08, decay=0.0)
        self.model_eval.compile(loss='mse',
                            optimizer=rmsprop,
                            metrics=['accuracy'])

        # ------------------ 构建目标神经网络 ------------------
        # 目标神经网络的架构必须和估计神经网络一样,但是不需要计算损失函数
        self.model_target = Sequential([
            Convolution2D(  # 就是Conv2D层
                batch_input_shape=(None, self.observation_shape[0], self.observation_shape[1],
                                   self.observation_shape[2]),
                filters=15,  # 多少个滤波器 卷积核的数目(即输出的维度)
                kernel_size=5,  # 卷积核的宽度和长度。如为单个整数,则表示在各个空间维度的相同长度。
                strides=1,  # 每次滑动大小
                padding='same',  # Padding 的方法也就是过滤后数据xy大小是否和之前的一样
                data_format='channels_last',  # 表示图像通道维的位置,这里rgb图像是最后一维表示通道
            ),
            Activation('relu'),
            # 输出(210, 160, 30)
            # Pooling layer 1 (max pooling) output shape (105, 80, 30)
            MaxPooling2D(
                pool_size=2,  # 池化窗口大小
                strides=2,  # 下采样因子
                padding='same',  # Padding method
                data_format='channels_last',
            ),
            # output(105, 80, 60)
            Convolution2D(30, 5, strides=1, padding='same', data_format='channels_last'),
            Activation('relu'),
            # (21, 16, 60)
            MaxPooling2D(5, 5, 'same', data_format='channels_first'),
            # 21 * 16 * 60 = 20160
            Flatten(),
            # LSTM(
            #     units=1024,
            #     return_sequences=True,  # True: output at all steps. False: output as last step.
            #     stateful=True,          # True: the final state of batch1 is feed into the initial state of batch2
            # ),
            Dense(512),
            Activation('relu'),
            Dense(self.n_actions),
        ])

我准备用一下午时间跑一跑,看看会不会有效果。

GitHub上源代码

猜你喜欢

转载自blog.csdn.net/u012465304/article/details/81328116