象棋菜刀群吧 关注:15贴子:34
  • 13回复贴,共1

象棋人工智能引擎和连线界面的开发介绍

只看楼主收藏回复

后面准备把开发过程中收集的资料整理公开出来,共同学习进步。
下面先把我2020年在CSDN原创的人工智能算法原理转载过来。
原文地址:
https://blog.csdn.net/askmeaskyou/category_10395513.html
AI人工智能(调包侠)速成之路一(人工智能极简史)
AI人工智能(调包侠)速成之路二(入门准备与开发平台选择)
AI人工智能(调包侠)速成之路三(开发环境安装TensorFlow 2.0)
AI人工智能(调包侠)速成之路四(开发环境安装PyTorch)
AI人工智能(调包侠)速成之路五(mnist手写数字识别1:如何调用模型)
AI人工智能(调包侠)速成之路六(mnist手写数字识别2:全连接层实现)
AI人工智能(调包侠)速成之路七(mnist手写数字识别3:cnn卷积神经网络实现)
AI人工智能(调包侠)速成之路八(RNN循环神经网络 Recurrent Neural Networks)
AI人工智能(调包侠)速成之路九(AlphaZero代码实战1:强化学习介绍)
AI人工智能(调包侠)速成之路十(AlphaZero代码实战2:蒙特卡洛树搜索)
AI人工智能(调包侠)速成之路十一(AlphaZero代码实战3:神经网络实现)
AI人工智能(调包侠)速成之路十二(AlphaZero代码实战4:人机对战实现)
AI人工智能(调包侠)速成之路十三(AlphaZero代码实战5:AI自对弈训练)
AI人工智能(调包侠)速成之路十四(中国象棋AI网络机器人:AI技术综合应用实现)
AI人工智能(调包侠)速成之路十五(中国象棋AI网络机器人:AI模型部署)


IP属地:云南1楼2022-04-19 08:27回复
    AI人工智能(调包侠)速成之路一(人工智能极简史)
    好吧,开始写点东西吧。缘起......
    1,什么是AI (ARTIFICIAL INTELLIGENCE)
    人工智能就是研究如何使计算机去做过去只有人才能做的智能工作,研究如何让计算机去完成以往需要人的智力才能胜任的工作。
    人工智能是一个大方向,而机器学习是实现人工智能的一种方法,深度学习则是机器学习的一个分支。
    2,1958年至今历史只有短短60多年
    从无到有,两次冬天,理论突破,爆发成长。
    3,模拟生物神经元结构,感知机的提出。
    用计算机来模拟神经元反应的过程,该模型将神经元简化为了三个过程:输入信号线性加权,求和,非线性激活(阈值法)。1962年,该方法被证明为能够收敛,理论与实践效果引起第一次神经网络的浪潮。然而学科发展的历史不总是一帆风顺的。1969年,数学家证明了感知器本质上是一种线性模型,只能处理线性分类问题,就连最简单的异或(XOR)问题都无法正确分类。这等于直接宣判了感知器的死刑,神经网络的研究也陷入了近20年的停滞。
    4,理论突破--多层感知机链式法则
    1986年多层感知器(MLP)的BP(Backpropagation)算法被提出,并采用Sigmoid进行非线性映射,有效解决了非线性分类和学习的问题。误差反向传播的链式法则可以说是机器学习的“灵魂”。BP算法在传统神经网络正向传播的基础上,增加了误差的反向传播过程。反向传播过程不断地调整神经元之间的权值和阈值,直到输出的误差达到减小到允许的范围之内,或达到预先设定的训练次数为止。BP算法完美的解决了非线性分类问题,该方法引起了人工神经网络的第二次热潮。
    1989年,理论上提出万能逼近定理,即对于任何闭区间内的一个连续函数f,都可以用含有一个隐含层的BP网络来逼近。该定理的发现极大的鼓舞了神经网络的研究人员。
    各种浅层机器学习模型被提出,经典的应用也相续出现。在空间上共用权值的卷积神经网络CNN(手写数字识别),在时间上共用权值的循环神经网络RNN(语言识别)。然而学科发展的历史不总是一帆风顺的。BP算法在误差梯度后向传递的过程中,后层梯度以乘性方式叠加到前层,由于Sigmoid函数的饱和特性,后层梯度本来就小,误差梯度传到前层时几乎为0“梯度消失”,因此无法对前层进行有效的学习,当神经网络的规模增大时,再使用BP算法还会出现“梯度爆炸”的问题,累计误差逐层递增无法收敛。这使得BP算法的发展受到了很大的限制,神经网络的热潮渐渐冷淡下去。
    5,技术突破--深度学习的诞生
    2006年 - 2012年提出了深层网络训练中梯度消失问题的解决方案:无监督预训练对权值进行初始化+有监督训练微调。其主要思想是先通过自学习的方法学习到训练数据的结构(自动编码器),然后在该结构上进行有监督训练微调。
    2011年,ReLU激活函数被提出,该激活函数能够有效的抑制梯度消失问题。
    6,深度学习的爆发
    爆发期2012 - 至今,理论层面并没有大的突破。但是围绕解决反向传播算法遇到的“梯度消失”与“梯度爆炸”问题,经过反复摸索得到了一些行之有效的处理技巧。使得训练深层神经网络可行,新的应用不断涌现。
    主要创新点
    (1)采用ReLU激活函数,极大增大收敛速度且从根本上解决了梯度消失问题。
    (2)由于ReLU方法可以很好抑制梯度消失问题,抛弃了“预训练+微调”的方法,完全采用有监督训练。也正因为如此,主流学习方法也因此变为了纯粹的有监督学习。
    (3)添加Dropout层减小过拟合,LRN层增强泛化能力/减小过拟合。
    (4)使用GPU加速模型计算。
    (5)基于GPU计算的使用,大数据批量训练大大提高了模型收敛速度。
    (6)BatchNorm训练模型的参数预处理为特定的统计分布,初始化非常重要。
    2016年3月,由谷歌(Google)旗下DeepMind公司开发的AlphaGo(基于深度学习)与围棋世界冠军、职业九段棋手李世石进行围棋人机大战,以4比1的总比分获胜;2016年末2017年初,该程序在中国棋类网站上以“大师”(Master)为注册帐号与中日韩数十位围棋高手进行快棋对决,连续60局无一败绩;2017年5月,在中国乌镇围棋峰会上,它与排名世界第一的世界围棋冠军柯洁对战,以3比0的总比分获胜。围棋界公认阿尔法围棋的棋力已经超过人类职业围棋顶尖水平。
    2017年,基于强化学习算法的AlphaGo升级版AlphaGo Zero横空出世。其采用“从零开始”、“无师自通”的学习模式,以100:0的比分轻而易举打败了之前的AlphaGo。除了围棋,它还精通国际象棋等其它棋类游戏,可以说是真正的棋类“天才”。此外在这一年,深度学习的相关算法在医疗、金融、艺术、无人驾驶等多个领域均取得了显著的成果。所以,也有专家把2017年看作是深度学习甚至是人工智能发展最为突飞猛进的一年。
    展望
    深度学习目前还处于发展阶段,不管是理论方面还是实践方面都还有许多问题待解决,不过由于我们处在了一个“大数据”时代,以及计算资源的大大提升,新模型、新理论的验证周期会大大缩短。人工智能时代的开启必然会很大程度的改变这个世界,无论是从交通,医疗,购物,军事等方面,未来难以预知,期待AGI的早日到来。


    IP属地:云南2楼2022-04-22 19:30
    回复
      AI人工智能(调包侠)速成之路二(入门准备与开发平台选择)
      基础知识
      1,高等数学
      编程就是控制计算机做各种运算,逻辑控制的部分很多,虽然用到的数学知识很灵活但是并不深奥。在机器学习与深度学习中却需要大量使用数学知识,这是给很多初学带来困难的主要原因之一。但是随着各种机器学习开发平台的出现,还有各种经典案例的推广,开发和使用人工智能越来越简便,各种复杂的数学理论都被打包成了各种对外的API接口,可以说只要能理解基本的概念,学会调用不同的接口(成为一个调包侠)也能用上当前最前沿的人工智能成果。
      2,Python语言
      “人生苦短,我用Python”,有编程基础的人其实很容易就能掌握Python,它的设计理念就是让程序逻辑隐藏起来,使用像语言对话的方式告诉它你想要做什么,然后它直接给你结果。更强大的地方在于各种功能强大的库,可以随时取用。世界上无数科学家、工程师设计出来的算法功能你可以直接取用,不但不需要重复制造“轮子”,甚至可以说各种“飞机大炮航空母舰”应有尽有,能限制你发挥的只在于你知不知道他们的存在,还有你的想象力有没有受到限制。后面的人工智能开发平台都可以看作是Python的一个库,熟悉了库的接口和用法基本上就算是入门了。
      3,C++语言
      深度学习中只有非常必要的情况下考虑使用C++,大部分情况是工业部署的时候,比如实时性要求很高的情况下。只在不得不用的时候使用。
      为什么机器学习必须使用开发框架
      所有框架都可以理解为矩阵加速计算和自动求导的科学计算库,是为了能方便的建立神经网络模型,然后加速训练每个神经元上权值。有了开发框架不需要手写CUDA就能跑GPU加速,自动帮你计算复杂复合函数的梯度,神经网络搭建只需调用平台接口就能实现,深度学习从此变得方便!
      主流开发平台介绍
      1, Tensorflow2
      注意这里推荐的是Tensorflow2.0以上的版本,因为Tensorflow1的版本和Tensorflow2可以说是完全不同的两个框架,如果你以前用过Tensorflow1的版本那么忘掉它吧。新手直接从Tensorflow2开始学习可以事半功倍。
      Tensorflow是全世界使用人数最多、社区最为庞大的一个框架,因为Google公司出品,所以维护与更新比较频繁,并且有着Python和C++的接口,教程也非常完善,同时很多论文复现的第一个版本都是基于Tensorflow写的,所以是深度学习界框架默认的老大。
      2, Pytorch
      PyTorch是当前难得的简洁优雅且高效快速的框架。
      3, 飞桨PaddlePaddle,百度深度学习平台
      PaddlePaddle是百度研发的开源开放的深度学习平台,是国内最早开源、也是当前唯一一个功能完备的深度学习平台。依托百度业务场景的长期锤炼,PaddlePaddle有最全面的官方支持的工业级应用模型,涵盖自然语言处理、计算机视觉、推荐引擎等多个领域,并开放多个领先的预训练中文模型,以及多个在国际范围内取得竞赛冠军的算法模型。国产框架不多,大家多支持啊!


      IP属地:云南3楼2022-04-28 20:07
      回复
        AI人工智能(调包侠)速成之路三(开发环境安装TensorFlow 2.0)
        极简三步安装
        1,Anaconda,Python3.8 安装
        下载地址:https://www.anaconda.com/products/individual#download-section
        Windows
        Python 3.8
        64-Bit Graphical Installer (466 MB)
        32-Bit Graphical Installer (397 MB)
        MacOS
        Python 3.8
        64-Bit Graphical Installer (462 MB)
        64-Bit Command Line Installer (454 MB)
        Linux
        Python 3.8
        64-Bit (x86) Installer (550 MB)
        64-Bit (Power8 and Power9) Installer (290 MB)
        2,TensorFlow 2.0 安装
        2.1. 配置国内源
        ▪ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
        ▪ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
        2.2. 显示源地址
        ▪ conda config --set show_channel_urls yes
        2.3. 照常安装
        ▪ conda create -n tf2 tensorflow-gpu
        ▪ conda activate tf2
        3,PyCharm / VScode
        下载地址:https://www.jetbrains.com/pycharm/download
        VScode下载地址: https://code.visualstudio.com/


        IP属地:云南4楼2022-04-30 10:42
        回复
          AI人工智能(调包侠)速成之路四(开发环境安装PyTorch)
          1,Anaconda,Python3.8 安装
          下载地址:https://www.anaconda.com/products/individual#download-section
          Windows
          Python 3.8
          64-Bit Graphical Installer (466 MB)
          32-Bit Graphical Installer (397 MB)
          MacOS
          Python 3.8
          64-Bit Graphical Installer (462 MB)
          64-Bit Command Line Installer (454 MB)
          Linux
          Python 3.8
          64-Bit (x86) Installer (550 MB)
          64-Bit (Power8 and Power9) Installer (290 MB)
          2,CUDA10.0 安装
          CUDA各版本官方下载地址:https://developer.nvidia.com/cuda-toolkit-archive
          CUDA10.0下载地址: https://developer.nvidia.com/cuda-10.0-download-archive
          3,Pycharm Community 安装
          下载地址:https://www.jetbrains.com/pycharm/download
          标题


          IP属地:云南5楼2022-05-05 08:54
          回复
            AI人工智能(调包侠)速成之路五(mnist手写数字识别1:如何调用模型)
            没有更好的例子了,人工智能入门Mnist是必经之路,经典中的经典,必须从这里开始。
            识别数字技术在深度学习领域已经非常成熟,常见的解决方案是OpenCV+Keras+TensorFlow,例如Github上有比较完善的车牌识别项目,我们先从最基础的手写数字识别开始机器学习实战之路吧。本文先介绍如何调用已经训练好的模型来识别图片数字,后续的文章再用全连接层和卷积神经网络来分别实现网络模型和训练代码。通过对比能更好的理解卷积神经网络共用权值、逐层抽象的概念。
            我把代码,模型,测试图片一起打包
            下载地址:https://download.csdn.net/download/askmeaskyou/12876950
            1.概念介绍:
            图像识别(Image Recognition)是指利用计算机对图像进行处理、分析和理解,以识别各种不同模式的目标和对像的技术。
            图像识别的发展经历了三个阶段:文字识别、数字图像处理与识别、物体识别。机器学习领域一般将此类识别问题转化为分类问题。
            手写识别是常见的图像识别任务。计算机通过手写体图片来识别出图片中的字,与印刷字体不同的是,不同人的手写体风格迥异,大小不一, 造成了计算机对手写识别任务的一些困难。
            数字手写体识别由于其有限的类别(0~9共10个数字)成为了相对简单 的手写识别任务。
            2.数据介绍:
            MNIST的下载链接:http://yann.lecun.com/exdb/mnist/
            MNIST是一个包含数字0~9的手写体图片数据集,图片已归一化为以手写数 字为中心的28*28规格的图片。
            MNIST由训练集与测试集两个部分组成,各部分 规模如下:
            训练集:60,000个手写体图片及对应标签
            测试集:10,000个手写体图片及对应标签
            2.调用模型:
            先学会使用科技成果才是“调包侠”的首要任务。
            import tensorflow as tf
            import numpy as np
            import cv2 as cv
            if __name__ == '__main__':
            img = cv.imread("6.bmp", cv.IMREAD_GRAYSCALE)
            img = np.asarray(img)
            img = img.reshape(1, 28, 28, 1)
            img_tensor = tf.convert_to_tensor(img, tf.float32)
            loaded = tf.saved_model.load('tf_mnist/1/')
            infer = loaded.signatures['serving_default']
            result = infer(img_tensor)['dense_1']
            print("before :", result)
            result = np.argmax(result)
            print("after :", result)
            下面是运行结果:
            before : tf.Tensor(
            [[9.1685351e-08 1.9940728e-16 6.5213286e-12 1.0845345e-15 1.0123441e-11
            7.6148967e-13 9.9999988e-01 1.7070938e-15 1.2981356e-11 8.4709163e-14]], shape=(1, 10), dtype=float32)
            after : 6
            为了照顾刚入门的读者,只能啰啰嗦嗦逐行解读下。
            import tensorflow as tf
            import numpy as np
            import cv2 as cv
            这里引入了三个Python库,tensorflow是机器学习的主流平台,神经网络的模型建立、训练、测试、导入、导出都有功能完整的实现和简洁的调用接口。numpy是科学计算库,大规模矩阵运算配合tensorflow使用。cv2是opencv-python,OpenCV的全称是:Open Source Computer Vision Library。OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。实现了图像处理和计算机视觉方面的很多通用算法。
            如果遇到错误“ImportError: No module named cv2”,没有找到cv2应该安装opencv-python 安装命令:pip install opencv-python
            img = cv.imread("test6.bmp", cv.IMREAD_GRAYSCALE)
            img = np.asarray(img)
            这里是用opencv的库函数接口读取测试图片“6.bmp”并且转换成numpy的数组形式。位图分辨率是28*28=728位的单通道黑白图片,每一个位上的数字范围是0到255。
            这样就把图片转换成了numpy的数组格式。如果图片不是28*28的分辨率就需要使用opencv的库对图片先进行预处理。
            img = img.reshape(1, 28, 28, 1)
            img_tensor = tf.convert_to_tensor(img, tf.float32)
            这里的代码是将numpy的数组转换形式然后调用tensorflow的库函数convert_to_tensor将numpy数组转换成了tensorflow的变量。
            reshape也是经常使用概念,就是将一长串数字做不同的分割理解,并不改变存储格式。如果对此不熟悉的需要先系统的学习下tensorflow2的相关知识。
            loaded = tf.saved_model.load('tf_mnist/1/')
            infer = loaded.signatures['serving_default']
            这里的代码是调用tensorflow的库函数加载训练好的pb模型,接着调用模型对外提供的接口。模型如何建立、训练、导出留在后面的文章详述,这里先学会使用前人的科技成果。
            result = infer(img_tensor)['dense_1']
            print("before :", result)
            result = np.argmax(result)
            print("after :", result)
            我们将图片转换出来的tensorflow变量传给训练好的模型,进行一次前向传播,就能得到模型给出来的反馈结果。使用所有神经网络模型就是这样一个套路,是不是很简单。
            总结下步骤:
            (1.数据预处理,2.转换成tensorflow的变量,3.传给训练好的神经网络模型,4.得到结果,5.将结果转换成明确的答案)
            看下神经网络返回的结果
            before : tf.Tensor(
            [[9.1685351e-08 1.9940728e-16 6.5213286e-12 1.0845345e-15 1.0123441e-11
            7.6148967e-13 9.9999988e-01 1.7070938e-15 1.2981356e-11 8.4709163e-14]], shape=(1, 10), dtype=float32)
            表示的是0到9十个数字的概率,我们选择概率最大的作为返回结果输出。这样就把手写数字图片的数字解读了出来。


            IP属地:云南6楼2022-05-06 15:59
            回复
              AI人工智能(调包侠)速成之路六(mnist手写数字识别2:全连接层实现)
              AI人工智能(调包侠)速成之路五(mnist手写数字识别1:如何调用模型)
              https://blog.csdn.net/askmeaskyou/article/details/108674860
              上次是直接叙述如何调用训练好的模型,这次就来看看神奇的神经网络是如何设计和训练导出的。
              我把代码,模型,测试图片一起打包
              下载地址:https://download.csdn.net/download/askmeaskyou/12876950
              前面的文章介绍过单层感知机只能处理线性分类问题,多层感知机加上非线性激活函数可以解决复杂的分类问题。
              AI人工智能(调包侠)速成之路一(人工智能极简史)
              下面就用tensorflow2来实现一个全连接多层神经网络的代码。
              import tensorflow as tf
              from tensorflow import keras
              from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics
              首先引入tensorflow2的库,然后引入keras。Keras是一个由Python编写的开源人工神经网络库,可以作为Tensorflow的高阶应用程序接口,进行深度学习模型的设计、调试、评估、应用和可视化。目前Keras已经集成到了Tensorflow里面,keras的设计是把大量内部运算都隐藏了,使用起来非常方便。
              通过Keras引入datasets(训练数据集管理), layers(网络模型层搭建), optimizers(网络优化器), Sequential(网络层打包的容器), metrics(测试度量器)。通过Keras引入5个工具进行模型搭建训练导出也是非常经典的套路。
              (x, y), (x_test, y_test) = datasets.mnist.load_data()
              这一行代码是把训练用的数据集打包下载(如果已经下载过会自动从缓存中加载),然后分为两个部分(x, y)用于训练模型,(x_test, y_test) 用于测试训练后的模型,当测试成功率满足要求后就停止训练。因为我们是学习经典案例所以一行代码轻松搞定了数据集的全部工作。如果是要开发一个其他应用的神经网络,要花费很大的时间精力来准备数据集和对应的标签数据。
              def preprocess(x, y):
              x = tf.cast(x, dtype=tf.float32) / 255.
              y = tf.cast(y, dtype=tf.int32)
              return x,y
              batchsz = 128
              db = tf.data.Dataset.from_tensor_slices((x,y))
              db = db.map(preprocess).shuffle(10000).batch(batchsz)
              这里的代码是构造数据集并对数据集预处理,preprocess(x, y) 就是预处理函数。将读取的训练数据转换到tensorflow变量中,x表示图片像素的值0到255,除与255就转换成0到1之间的小数,y表示的是图片对应的标签值。
              shuffle(10000).batch(batchsz)的作用是把数据随机打散然后选一个batch。
              db_test = tf.data.Dataset.from_tensor_slices((x_test,y_test))
              db_test = db_test.map(preprocess).batch(batchsz)
              测试的数据集也做同样的处理
              到这里训练和测试用的数据集都准备好了,下面通过容器来构造一个5层的全连接神经网络
              model = Sequential([
              layers.Dense(256, activation=tf.nn.relu), # [b, 784] => [b, 256]
              layers.Dense(128, activation=tf.nn.relu), # [b, 256] => [b, 128]
              layers.Dense(64, activation=tf.nn.relu), # [b, 128] => [b, 64]
              layers.Dense(32, activation=tf.nn.relu), # [b, 64] => [b, 32]
              layers.Dense(10) # [b, 32] => [b, 10], 330 = 32*10 + 10
              ])
              看到构建神经网路模型的代码也是非常简洁,每一行就对应一层网络,网络的节点数大小原则上是逐层减少,只需要注意输入和输出的维度要设计好。除了最后一层外,其他层都加上了激活函数”activation=tf.nn.relu“,这个函数也很简单,但它是一个非线性函数,这样几层网络堆叠起来就可以求解复杂的分类问题了。
              relu函数:
              model.build(input_shape=[None, 28*28])
              model.summary()
              model.build是构建模型输入的维度,我们输入的是28*28像素的维度,model.summary()可以将设计好的网络结构打印出来。
              可以看到上面的5层网络包含的连接数已经非常多了,每个节点都有需要训练的权值,总的参数量是244522个。
              optimizer = optimizers.Adam(lr=1e-3)
              设置优化器和学习率。
              到这里神经网络模型也准备好了,下面就是不断循环的抽取训练数据进行前向传播获得反馈结果,然后用反馈的结果和标签数据比较,使用优化器不断更新节点参数,让神经网络反馈的结果和标签数据的结果越来越接近(误差越来越小)。在训练的过程中用测试数据统计成功率,成功率超过预期后就可以停止训练了。
              训练代码还涉及到一些tensorflow2知识点,如果有疑问还是要系统补充下相关知识。Tensorflow2.0的使用方法参照Tensroflow官方教程。下面对几个关键内容简单做个解释。
              logits = model(x) #前向传播获得结果就只需要这样一行代码,非常简单。
              y_onehot = tf.one_hot(y, depth=10) #onehot编码也是非常常用的,这里就是把数字变成[0,0,0,0,0,0,0,0,1,0]格式。
              loss_mse = tf.reduce_mean(tf.losses.MSE(y_onehot, logits))
              loss_ce = tf.losses.categorical_crossentropy(y_onehot, logits, from_logits=True)
              loss_ce = tf.reduce_mean(loss_ce)
              误差函数的选取也是非常经典的问题,一般数值回归的问题选择MSE均方误差函数,多分类问题选择crossentropy交叉熵损失函数。
              完整代码,模型,测试图片一起打包
              下载地址:https://download.csdn.net/download/askmeaskyou/12876950
              这里用了最基础的全连接层堆叠,可以看出来层数的增加会增加很多的节点连接,神经网络的训练就是要不断修改每个连接节点的权值参数,有没有办法让节点之间的连接共享参数,这样就能大大减少需要训练的权值参数。下一篇文章,我们用CNN卷积神经网络来实现模型。


              IP属地:云南8楼2022-05-13 16:10
              回复
                AI人工智能(调包侠)速成之路七(mnist手写数字识别3:cnn卷积神经网络实现)
                AI人工智能(调包侠)速成之路五(mnist手写数字识别1:如何调用模型)
                AI人工智能(调包侠)速成之路六(mnist手写数字识别2:全连接层实现)
                相关代码,模型,测试图片一起打包
                下载地址:https://download.csdn.net/download/askmeaskyou/12876950
                前面文章介绍了如何使用训练好的神经网络模型,并借助mnist这个案例学习如何用全连接层设计和训练神经网络。但是全连接层随着输入维度的增加,节点也要相应增加,对应的连接数更是指数级增加,如果我们输入的不是一个28*28像素的单通道黑白图片,而是一个张现在智能手机拍的照片(千万级像素),那用全连接层去堆叠做分类任务基本就是不可能完成的任务了。
                1,基础概念:卷积层介绍
                我们使用一个小窗口从上到下、从左到右的滑动窗口扫描整个输入的"大图",然后把每次扫描到的内容做一个卷积变换(重叠对应的元素相乘再累加)记录下来。选取的小窗口就叫卷积核,变换后记录下来的信息是对输入信息的一种抽象转换叫“feature map”,我们可以理解为一个新的“图片”,新的“图片”和输入图片有一样的特征信息,只是改变了记录形式。
                这样不论输入的图片有多大,我们总是用一个小窗口(通常是3*3或者1*1,实践证明窗口越小分类效果好,参数还少)去扫描大图。如上动图显示,这个小窗口与大图的连接每次只有9个,而且在扫描的过程中9个连接的参数是共享的,通过这样的”翻译“,神经网络层与层之间需要训练的连接参数数量级的减少了。“翻译”出来的信息“feature map”还可以多次”翻译“,逐层抽象,最后得到一个输入图片的“特征值”,再用得到的“特征值”来做分类任务。
                2基础概念:池化层介绍
                类似于卷积层,我们用一个小窗口从上到下、从左到右的滑动窗口扫描整个输入的"大图",然后把每次扫描到的内容做一个下采样变换(取最大值或者取平均值或者取随机值)记录下来。选取的小窗口就叫池化核,变换后记录下来的信息是对输入信息的一种抽象转换也是“feature map”。池化层通常都是配合在卷积层之后使用,作用和ReLU函数相似。
                卷积层的tensorflow2代码实现如下:
                layers.Conv2D(filters=32, kernel_size=(3,3), padding='same',input_shape=(28,28,1), activation='relu')
                filters=32参数的意思是使用32个小窗口同时做扫描,kernel_size=(3,3)参数的意思是小窗口的大小是3*3个格子,padding='same'参数的意思是通过在输入图片的外围补充元素的方式,使得转换后的图片尺寸跟输入图片的尺寸一样大,
                input_shape=(28,28,1),参数的意思是输入图片维度格式, activation='relu'参数是使用的激活函数。
                池化层的tensorflow2代码实现如下:
                layers.MaxPooling2D(pool_size=(2, 2))
                pool_size=(2, 2)参数就是池化核窗口的大小是2*2个格子。
                通过上面的参数我们可以任意的控制转换后"feature map"的维度格式,比如输入图片sharp是[28,28,1]的变量我们可以理解为28行28列1个通道的黑白图片,经过转换可以变成sharp是[1,1,64]的变量。表示的还是同一张图片,但是表示的维度方式已经(通过卷积层和池化层)改变了。通常将转换后的"feature map"作为特征值再通过tf.keras.layers.Flatten()打平连接到全连接层上做为最后的输出。
                3,cnn卷积神经网络实现
                有了上面的基础概念现在我们可以写出cnn卷积神经网络的实现代码了。
                model = Sequential([
                layers.Conv2D(filters=32, kernel_size=(3,3), padding='same',input_shape=(28,28,1), activation='relu'),
                layers.MaxPooling2D(pool_size=(2, 2)),
                layers.Conv2D(filters=64, kernel_size=(3,3), activation='relu'),
                layers.MaxPooling2D(pool_size=(2, 2)),
                layers.Conv2D(filters=64, kernel_size=(3,3), activation='relu'),
                tf.keras.layers.Flatten(),
                layers.Dense(64, activation='relu'),
                layers.Dense(10,activation='softmax')
                ])
                model.summary()可以将设计好的网络结构打印出来。
                到这里神经网络模型也准备好了,下面就是不断循环的抽取训练数据进行前向传播获得反馈结果,然后用反馈的结果和标签数据比较,使用优化器不断更新节点参数,让神经网络反馈的结果和标签数据的结果越来越接近(误差越来越小)。在训练的过程中用测试数据统计成功率,成功率超过预期后就可以停止训练了。
                #训练配置
                model.compile(loss='sparse_categorical_crossentropy',optimizer='adam', metrics=['accuracy'])
                #开始训练
                model.fit(x_train,y_train, epochs=2, validation_data=db_test, callbacks=[save_model_cb])
                训练代码也有现成的接口可以直接调用。参数内容在前面的文章中已经做过介绍,涉及到一些tensorflow2知识点,如果有疑问还是要系统补充下相关知识。Tensorflow2.0的使用方法参照Tensroflow官方教程。
                此文相关代码,模型,测试图片一起打包
                下载地址:https://download.csdn.net/download/askmeaskyou/12876950


                IP属地:云南9楼2022-05-22 10:34
                回复
                  AI人工智能(调包侠)速成之路八(RNN循环神经网络 Recurrent Neural Networks)
                  未来的程序员必定需要掌握调用神经网路模型实现人工智能功能的能力,(调包侠)一定是未来程序员的必经之路。好在新工具平台的不断出现,功能调用越来越向API方向发展,补上相关知识继续上路吧。
                  RNN循环神经网络与时空序列数据
                  RNN全称循环神经网络(Recurrent Neural Networks),是用来处理时空序列数据的。语言、文章、股票走势这些都是常见的序列信号,我们交谈的时候要听懂一句话的内容,首先要依次听懂和记住前面每个单词,然后把后续听到的单词内容综合到前面的信息里面去,最后才能理解整个句子的内容。例如:“经过调查伊拉克政府没有大规模杀伤性武器,非也......”。一个句子中前后单词并不是独立的先后顺序也不能打乱。RNN循环神经网路就是专门处理这类时空序列数据的。
                  时空序列数据的表示与转换 Sequence Embedding
                  时空数据常见的是表格的形式表示例如:股票历史数据中的最低价、最高价、开盘价、收盘价、交易量、交易额、跌涨幅等。
                  语言信息数字采样
                  声音的波形数字采样也可以直接计算和处理, 比较困难的是非数值类型的信号,例如自然语言和文字的数字化表示。好在这些基础的问题现在的工具都已经内部集成了解决方案。只需要设置下参数就可以使用了。
                  from tensorflow.keras import layers
                  self.embedding = layers.Embedding(total_words, embedding_len, input_length=max_review_len)
                  实战LSTM:情感分类问题
                  LSTM全称长短期记忆人工神经网络(Long-Short Term Memory),是对RNN循环神经网络的经典实现和解决方案。训练集我们使用的是 IMDB 数据集。这个数据集包含 25000 条电影评论数据,其中 12500 条正向数据,12500 条负向数据。要实现的目标是让神经网络能读懂评论信息,自动分辨出好评和差评。
                  import os
                  os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
                  import tensorflow as tf
                  import numpy as np
                  from tensorflow import keras
                  from tensorflow.keras import layers
                  tf.random.set_seed(22)
                  np.random.seed(22)
                  assert tf.__version__.startswith('2.')
                  batchsz = 128
                  total_words = 10000 # 最大词汇量
                  max_review_len = 80 # 最长句子单词数(短的句子后面补齐长度,长的句子超过80个单词截断丢弃)
                  embedding_len = 100 # 转换后的变量维度
                  (x_train, y_train), (x_test, y_test) = keras.datasets.imdb.load_data(num_words=total_words)
                  # x_train:[b, 80]
                  # x_test: [b, 80]
                  x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen=max_review_len)
                  x_test = keras.preprocessing.sequence.pad_sequences(x_test, maxlen=max_review_len)
                  db_train = tf.data.Dataset.from_tensor_slices((x_train, y_train))
                  db_train = db_train.shuffle(1000).batch(batchsz, drop_remainder=True)
                  db_test = tf.data.Dataset.from_tensor_slices((x_test, y_test))
                  db_test = db_test.batch(batchsz, drop_remainder=True)
                  上面的代码加载数据集分成训练和测试数据。下面先定义循环神经网络模型。
                  class MyRNN(keras.Model):
                  def __init__(self, units):
                  super(MyRNN, self).__init__()
                  # transform text to embedding representation
                  # [b, 80] => [b, 80, 100]
                  self.embedding = layers.Embedding(total_words, embedding_len,
                  input_length=max_review_len)
                  # [b, 80, 100] , h_dim: 64
                  self.rnn = keras.Sequential([
                  layers.LSTM(units, dropout=0.5, return_sequences=True, unroll=True),
                  layers.LSTM(units, dropout=0.5, unroll=True)
                  ])
                  # fc, [b, 80, 100] => [b, 64] => [b, 1]
                  self.outlayer = layers.Dense(1)
                  def call(self, inputs, training=None):
                  # [b, 80]
                  x = inputs
                  # embedding: [b, 80] => [b, 80, 100]
                  x = self.embedding(x)
                  # x: [b, 80, 100] => [b, 64]
                  x = self.rnn(x,training=training)
                  # out: [b, 64] => [b, 1]
                  x = self.outlayer(x)
                  # p(y is pos|x)
                  prob = tf.sigmoid(x)
                  return prob
                  定义的神经网络用了容器keras.Sequential,里面是两层LSTM,第一层需要return_sequences=True参数,dropout是一个模型优化方法。并且调用layers.Embedding功能将单词编码成了100维的变量。
                  下面就可以将转换后的变量用来训练神经网络模型了。
                  if __name__ == '__main__':
                  units = 64
                  epochs = 4
                  model = MyRNN(units)
                  model.compile(optimizer = keras.optimizers.Adam(0.001),
                  loss = tf.losses.BinaryCrossentropy(),
                  metrics=['accuracy'])
                  model.fit(db_train, epochs=epochs, validation_data=db_test)
                  model.evaluate(db_test)
                  循环神经网络的发展:时空序列预测
                  循环神经能从历史信息里面提取出规律并对后续的数据给出预测,于是网上出现了大量使用LSTM模型预测股票走势,预测彩票结果的文章。如果真能实现这种效果那学习人工智能真是花多大的代价都值得了,巴菲特、西蒙斯什么老古董都入土吧!如果价格的变化走势能用一个公式表达出来,那么用循环神经网络肯定是能拟合预测出未来走势,问题转换成了“价格的变化走势能否用一个公式表达出来?”很明显答案是否定的。
                  近年来流行的行为金融学给出了一些定性的非理性认知偏差(过度自信、盲信权威、从众效应、盲信喜好)。用神经网络去定量研究特定情形下,特定时间段的非理性行为或许是个不错的方向。成功难以复制,失败或可避免。
                  用ST-LSTM预测学习的循环神经网络 PredRNN
                  论文下载: http://ise.thss.tsinghua.edu.cn/~mlong/doc/predrnn-nips17.pdf
                  Casual LSTM和GHU解决时空预测学习中的深度困境 PredRNN++
                  论文下载地址:http://proceedings.mlr.press/v80/wang18b/wang18b.pdf
                  当前理论发展迅速,工具明显跟不上进度了。(调包侠)只能等待最新的集成工具出来。
                  ————————————————
                  版权声明:本文为CSDN博主「askmeaskyou」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
                  原文链接:https://blog.csdn.net/askmeaskyou/article/details/108932690


                  IP属地:云南10楼2022-05-23 08:33
                  回复
                    AI人工智能(调包侠)速成之路九(AlphaZero代码实战1:强化学习介绍)
                    前言
                    AlphaGo战胜人类围棋冠军已经好几年过去了,这个话题已经不热了,国内介绍这个项目原理的技术文章也非常多。遗憾的是国内并没有出现几个类似的成功案例,这个问题值得玩味。是不是在实践的路上有很多隐形的关键问题没有公开出来,就算把AlphaGo的源码公开,我们拿过来也做不出一个成功的应用呢?
                    AlphaGo成功之后DeepMind又放出了更加通用的 AlphaZero 的论文。AlphaZero综合应用了深度学习、启发式搜索MCTS、自对弈强化学习、神经网络共享(分类和回归问题使用同一个网络)、数据增强等等技术。纯粹靠自己跟自己下棋这样的“左右互搏”就练成了高手,战胜了前辈AlphaGo,令人炫目。
                    可以预见AlphaZero系统的应用范围和前景都非常广泛,希望更多的爱好者能加入进来丰富应用案例,做出更多超越人类单项智力的软件系统。
                    什么是强化学习(Reinforcement Learning)
                    强化学习是智能体(Agent)以“试错”的方式进行学习,通过与环境进行交互获得的奖赏指导行为,目标是使智能体获得最大的奖赏,强化学习不同于连接主义学习中的监督学习,主要表现在强化信号上,强化学习中由环境提供的强化信号是对产生动作的好坏作一种评价(通常为标量信号),而不是告诉强化学习系统RLS(reinforcement learning system)如何去产生正确的动作。由于外部环境提供的信息很少,RLS必须靠自身的经历进行学习。通过这种方式,RLS在行动-评价的环境中获得知识,改进行动方案以适应环境。
                    强化学习原理
                    强化学习原理简单说就是”胡罗卜加大棒“,建立一个封闭环境并通过明确的奖惩标识给出反馈信息,让神经网路在不断的试错过程中学习如何趋利避害,最后通过观察环境就能给出类似“人的直觉”一样的行为,并能从不断试错的过程中明白奖惩规则的规律,并能依此给当前所处环境的优劣给出一个客观评价。神经网络根据环境状态一步一步的寻找动作轨迹,使累计回报最大,目的就是找到最优的策略。
                    马尔科夫决策过程
                    在强化学习中,马尔科夫决策过程(Markov decision process, MDP)是对完全可观测的环境进行描述的,也就是说观测到的状态内容完整地决定了决策的需要的特征。几乎所有的强化学习问题都可以转化为马尔科夫决策过程。
                    马尔可夫决策过程简单说就是一个智能体(Agent)采取行动(Action)从而改变自己的状态(State)获得奖励(Reward)与环境(Environment)发生交互的循环过程。
                    马尔科夫决策要求:
                    能够检测到理想的状态。
                    可以多次尝试(死了重来、输了重来等)。
                    系统的下个状态只与当前状态信息有关,而与更早之前的状态无关。在决策过程中还和当前采取的动作有关。
                    AlphaZero代码实战
                    作为代码实战前的准备,这里简单介绍了相关的背景知识。强化学习求解方法很多,下篇文章介绍AlphaZero使用的蒙特卡洛方法。并动手将学到的想法转换成代码。后续会通过一个五子棋AI的案例把AlphaZero系统的代码一一实现。
                    AlphaZero代码实战系列 源代码打包
                    下载地址:https://download.csdn.net/download/askmeaskyou/12931806
                    ————————————————
                    版权声明:本文为CSDN博主「askmeaskyou」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
                    原文链接:https://blog.csdn.net/askmeaskyou/article/details/108993981


                    IP属地:云南11楼2022-05-24 09:03
                    回复
                      AI人工智能(调包侠)速成之路十(AlphaZero代码实战2:蒙特卡洛树搜索)
                      蒙特卡罗方法(Monte Carlo method)
                      什么是蒙特卡罗方法
                      用通过概率实验所求的概率估计来估计一个未知量,这样的方法统称为蒙特卡罗方法(Monte Carlo method)。
                      为什么需要蒙特卡洛方法
                      在现实世界中,大量存在一些复杂性过程,由于这类模型含有不确定的随机因素,我们很难直接用一个确定性模型来分析和描述。面对这种情况.数据科学家难以作定量分析,得不到解析的结果,或者是虽有解析结果,但计算代价太大以至不能使用。在这种情况下,可以考虑采用 Monte Carlo 方法。
                      蒙特卡洛方法的思想
                      如果我们将宇宙中的每个事物都抽象为表象和里像这两种表现形式,里像是我们不可知的,只有上帝才知道,但是表象是我们可以通过物理手段观测得到的,而连接里像和表象的元定理就是因果律,因为因果律的存在,使得我们可以通过表象反推出里像,进而探问世界的真像。当因果律不太明确的时候,我们就通过大量的模拟统计来定量计算结果。
                      蒙特卡洛树搜索(Monte Carlo Tree Search,MCTS)算法
                      什么是蒙特卡罗树搜索方法
                      蒙特卡洛树搜索说就是将蒙特卡洛方法这种随机模拟的方法应用到树搜索上。蒙特卡洛树搜索是一种基于树结构的蒙特卡洛方法,是一种确定规则驱动的启发式随机搜索算法。
                      为什么需要蒙特卡洛树搜索方法
                      基本上程序员对树搜索都很熟悉,常用的是广度优先搜索和深度优先搜索,但是AlphaZero系统下围棋的时候要搜索的局面状态有多少种呢?我们可以简单估算下数量级。围棋盘面上有19*19=361个点,每个落子点只存在三种可能(黑、白、空),因此盘面的上限为3的361次方种。如果按照300步来计算对弈一盘棋要遇到的局面选择,第一步为361种可能性,第二步为360,第三步为359······所以总数为361!(阶乘),这个数字大约等于1.73E+686。宇宙中原子总数为1.67E+80。所以人类对弈围棋的时候很多选择是根据经验排除了很多选项,然后少数几个选择里靠“直觉”加估计一个更有利的选择。蒙特卡洛树搜索就是要模拟这个过程,先选择几个大的先验概率方向搜索,然后按先验概率模拟对弈到结束,再通过对弈结果给出的奖励信号反向传播更新局面估值,最后选择一个估值有利的局面。
                      MCTS的5个主要核心部分:
                      树结构:树结构定义了一个可行解的解空间,每一个叶子节点到根节点的路径都对应了一个解(solution),解空间的大小为2N(N等于决策次数,即树深度)
                      蒙特卡洛方法:MSTC不需要事先给定打标样本,随机统计方法充当了驱动力的作用,通过随机统计实验获取观测结果。
                      损失评估函数:有一个根据一个确定的规则设计的可量化的损失函数(目标驱动的损失函数),它提供一个可量化的确定性反馈,用于评估解的优劣。从某种角度来说,MCTS是通过随机模拟寻找损失函数代表的背后”真实函数“。
                      反向传播线性优化:每次获得一条路径的损失结果后,采用反向传播(Backpropagation)对整条路径上的所有节点进行整体优化,优化过程连续可微
                      启发式搜索策略:算法遵循损失最小化的原则在整个搜索空间上进行启发式搜索,直到找到一组最优解或者提前终止
                      算法的优化核心思想总结一句话就是:在确定方向的渐进收敛(树搜索的准确性)和随机性(随机模拟的一般性)之间寻求一个最佳平衡。体现了纳什均衡的思想精髓。
                      MCTS搜索就是建立一棵树的过程。蒙特卡罗树搜索大概可以被分成四步。选择(Selection),拓展(Expansion),模拟(Simulation),反向传播(Backpropagation)。下面我们结合一个五子棋AI的案例代码逐个来分析。
                      建立一棵树
                      class TreeNode:
                      """
                      蒙特卡洛树的一个节点,每个节点存了Q值,P值,N值
                      """
                      def __init__(self, parent, prior_p):
                      self._parent = parent
                      self._children = {} # 键是动作值,值是节点
                      self._n_visits = 0
                      self._Q = 0
                      self._P = prior_p
                      MCTS本质上是我们来维护一棵树,这棵树的每个节点保存了每一个局面(situation)该如何走子(action)的信息。这些信息是,N(s, a)是访问次数,W(s, a)是总行动价值,Q(s, a)是平均行动价值,P(s, a)是被选择的概率。
                      选择(Selection)
                      def select(self, c_puct):
                      """
                      选择所有子节点中Q+u(P)最大的返回。
                      :param c_puct: 一个在范围(0, inf)的值,控制Q和P的比例
                      :return: 二元组(action, next_node)
                      """
                      return max(self._children.items(), key=lambda act_node: act_node[1].get_value(c_puct))
                      def get_value(self, c_puct):
                      """
                      得到该节点的Q+u(P)值
                      :param c_puct: 一个在范围(0, inf)的值,控制Q和P的比例
                      :return: 该节点的Q+u(P)值
                      """
                      u = c_puct * self._P * np.sqrt(self._parent._n_visits) / (1 + self._n_visits)
                      return self._Q + u
                      每次模拟的过程都一样,从父节点的局面开始,选择一个走子。比如开局的时候,所有合法的走子都是可能的选择,那么我该选哪个走子呢?这就是select要做的事情。MCTS选择Q(s, a) + U(s, a)最大的那个action。c_puct是一个决定探索水平的常数;这种搜索控制策略最初倾向于具有高先验概率和低访问次数的行为,但是渐近地倾向于具有高行动价值的行为。
                      拓展(Expansion)
                      def expand(self, action_priors):
                      """
                      展开一个叶子节点。
                      :param action_priors: 一个元素为(action, P)的列表
                      """
                      for action, prob in action_priors:
                      if action not in self._children:
                      self._children[action] = TreeNode(self, prob)
                      我们要接着上个局面选择action,但是这个局面是个叶子节点。就是说之后可以选择哪些action不知道,这样就需要expand了,通过expand得到一系列可能的action节点。这样实际上就是在扩展这棵树,从只有根节点开始,一点一点的扩展。这个时候要用我们的神经网络出马。把当前的局面作为输入传给神经网络,神经网络会返回给我们一个action向量p和当前胜率v。其中action向量是当前局面每个合法action的走子概率。这样在当前局面下,所有可走的action以及对应的概率p就都有了。当然,神经网络还没有训练好,一开始给出的都是随机值,之后通过不断的训练,神经网络给出的估值会越来越好。
                      模拟(Simulation)
                      class MCTS:
                      """
                      蒙特卡洛树及其搜索方法。
                      """
                      def __init__(self, policy_value_fn, c_puct=5, n_playout=300):
                      """
                      :param policy_value_fn: 论文里面的(p,v)=f(s)函数。接受一个board作为参数并返回一个(动作,概率)列表和在[-1, 1]范围的局面胜率的函数
                      :param c_puct: 论文里面的c_puct。一个在范围(0, inf)的数字,控制探索等级。值越小越依赖于Q值,值越大越依赖于P值
                      :param n_playout: 找MCTS叶子节点次数,即每次搜索次数
                      """
                      self._root = TreeNode(None, 1.0)
                      self._policy = policy_value_fn
                      self._c_puct = c_puct
                      self._n_playout = n_playout
                      def _playout(self, state):
                      """
                      执行一次蒙特卡洛搜索,找到一个叶子节点,并更新路径上所有节点的值。
                      :param state: 一个Board对象,在搜索过程中这个Board对象的状态会随之改变,所以这个参数传进来前需要复制一份。
                      """
                      node = self._root
                      while not node.is_leaf(): # 找到一个叶子节点
                      action, node = node.select(self._c_puct)
                      state.do_move(action)
                      action_probs, leaf_value = self._policy(state) # 得到一个相对于当前玩家的(action, probability)列表和在范围[-1, 1]的V值
                      end, winner = state.game_end() # 检查游戏是否结束
                      if not end:
                      node.expand(action_probs)
                      else:
                      if winner == -1: # 平局V值为0
                      leaf_value = 0.0
                      else:
                      leaf_value = (1.0 if winner == state.get_current_player() else -1.0) # 当前玩家赢了V值为1,输了V值为-1
                      # 更新路径上所有节点的值
                      node.update_recursive(-leaf_value)
                      模拟自我对弈的过程。模拟结束后,基本上能覆盖大多数高先验概率的棋局和着法,每步棋该怎么下,下完以后胜率是多少,得到什么样的局面都能在树上找到。然后从树上选择当前局面应该下哪一步棋,当模拟结束后,对于当前局面(就是树的根节点)的所有子节点就是每一步对应的action节点,选择访问计数大的行为。然后从多个action中选一个,这其实是多分类问题。
                      反向传播(Backpropagation)
                      def update(self, leaf_value):
                      """
                      根据叶子节点的V值更新本节点的N值和Q值。
                      :param leaf_value: 从当前玩家视角的子树评估值
                      """
                      self._n_visits += 1
                      self._Q += (leaf_value - self._Q) / self._n_visits
                      任意一个局面(就是节点),要么被展开过(expand),要么没有展开过(就是叶子节点)。展开过的节点可以使用Select选择动作进入下一个局面,叶子节点就继续展开。下一个局面仍然是这个过程,如果展开过还是可以通过Select进入下下个局面,这个过程一直持续下去直到这盘棋分出胜平负了为止。就是说我现在下了一步棋,不管这步棋是好棋还是臭棋,只有下完整盘期分出胜负,才能给我下的这步棋评分。然后把评分从终局逐层向上返回。
                      至此MCTS算法就分析完了。AlphaZero巧妙了使用MCTS搜索树和神经网络一起,通过MCTS搜索树优化神经网络参数,反过来又通过优化的神经网络指导MCTS搜索。两者一主一辅,非常优雅的解决了这类状态完全可见,信息充分的棋类问题。我们在下一篇讨论给局面状态打分的神经网络如何实现。
                      AlphaZero代码实战系列 源代码打包
                      下载地址:https://download.csdn.net/download/askmeaskyou/12931806


                      IP属地:云南12楼2022-05-25 10:14
                      回复
                        AI人工智能(调包侠)速成之路十一(AlphaZero代码实战3:神经网络实现)
                        AlphaZero巧妙了使用MCTS搜索树和神经网络一起,通过MCTS搜索树优化神经网络参数,反过来又通过优化的神经网络指导MCTS搜索。两者一主一辅,非常优雅的解决了这类状态完全可见,信息充分的棋类问题。前面结合一个五子棋AI的案例代码实现了蒙特卡洛树搜索,这次我们使用Tensorflow2来实现神经网络的部分。
                        AI人工智能(调包侠)速成之路十(AlphaZero代码实战2:蒙特卡洛树搜索)
                        神经网络输入特征的设计
                        神经网络的输入特征设计等同于传统程序设计里面的“数据结构”设计,在Tensorflow2中使用Numpy多维数组作为输入,然后转换为tensor变量再经过不同的网络层逐层变换,最后按我们设计的分类问题或者数值回归问题输出结果。
                        输入特征基本上按照解决问题所需要的充分必要信息来设计,如果硬件条件允许也可以多增加输入信息,增加的信息要能帮助到解决问题,否则只是浪费资源和增加消耗的时间。比如我们前面介绍(mnist手写数字识别)输入信息是28*28*1,我们也可以输入彩色图片信息28*28*3,输入信息增加了三倍但是对于识别数字这个问题来说是没有必要的,但是如果我们的问题不但要识别数字还要分辨颜色的话就必须输入彩色图片信息28*28*3,否则分辨颜色的功能就无法实现。
                        AlphaZero围棋输入的是19×19×17维度的图像栈 ,我们这个五子棋的网络用15×15×4维度已经够用了。
                        # 定义网络结构
                        # 1. 输入
                        self.input_states = tf.keras.layers.Input([4, board_width, board_width], dtype='float32', name='input_states') # TODO C plain x 2
                        self.input_state = tf.transpose(self.input_states, [0, 2, 3, 1], name="input_state")
                        # 2. 中间层
                        # 2.1 卷积层
                        X = tf.keras.layers.Conv2D(filters=64, kernel_size=[3, 3], padding="same", data_format="channels_last")(self.input_state)
                        X = tf.keras.layers.BatchNormalization(epsilon=1e-5, fused=True)(X)
                        X = tf.nn.relu(X)
                        为了程序代码方便我们输入用4*15*15的格式,输入后用tf.transpose将格式转换为15*15*4格式。接着使用一个卷积层变换输入信息(mnist手写数字识别3:cnn卷积神经网络实现 卷积层忘记的看这里)。
                        Batch Normalization
                        Batch Normalization,简称BN,来源于《Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift》,中文叫批量归一化/批量标准化?好像没有很好的翻译。用一个Batch的均值和方差作为对整个数据集均值和方差的估计。随着网络的深度增加,每层特征值分布会逐渐的向激活函数的输出区间的上下两端(激活函数饱和区间)靠近,这样继续下去就会导致梯度消失。BN就是通过方法将该层特征值分布重新拉回标准正态分布,特征值将落在激活函数对于输入较为敏感的区间,输入的小变化可导致损失函数较大的变化,使得梯度变大,避免梯度消失,同时也可加快收敛。
                        深度神经网络中每一个中间层都是下一层的输入,在输入下一层之前用tf.keras.layers.BatchNormalization做一下变换。
                        深度残差网络ResNet
                        深度残差网络ResNet是2015年何凯明博士(广东省高考状元,进入清华,2011年香港中文大学博士毕业后正式加入微软亚洲研究院MSRA)在MSRA提出的。之前的神经网络超过20层以后就变得很难训练成功,ResNet出来以后网络深度可以达到上千层,深度神经网络取得了质的飞跃。
                        深度学习目前进展取决于技巧:初始权值选择,局部感受野,权值共享等等,但使用更深层的网络时,依然要面对反向传播时梯度消失这类传统困难,层数越多,训练错误率与测试错误率反而升高。ResNet相当于将学习目标改变了,不再学习如何完整的输出结果,而是学习输入和输出的差别,即残差。数学上可以证明加入“短接”是对训练参数最好的选择。
                        # 2.2 残差层
                        def residual_block(input):
                        X = tf.keras.layers.Conv2D(filters=64, kernel_size=[3, 3], padding="same", data_format="channels_last")(input)
                        X = tf.keras.layers.BatchNormalization(epsilon=1e-5, fused=True)(X)
                        X = tf.nn.relu(X)
                        X = tf.keras.layers.Conv2D(filters=64, kernel_size=[3, 3], padding="same", data_format="channels_last")(X)
                        X = tf.keras.layers.BatchNormalization(epsilon=1e-5, fused=True)(X)
                        add = tf.add(X, input)
                        return tf.nn.relu(add)
                        for i in range(7):
                        X = residual_block(X)
                        目前残差层还需要自己实现,实现代码如上。短接操作使用 tf.add,要注意两个相加的内容维度要保持一致。定义完残差层就可以用一个循环堆叠多层使用,上面代码使用7个残差层串联起来。
                        网络输出 概率向量P数组输出:
                        # 3. P数组输出
                        Y = tf.keras.layers.Conv2D(filters=2, kernel_size=[1, 1], padding="same", data_format="channels_last")(X)
                        Y = tf.keras.layers.BatchNormalization(epsilon=1e-5, fused=True)(Y)
                        Y = tf.nn.relu(Y)
                        self.action_conv_flat = tf.reshape(Y, [-1, 2 * board_width * board_width], name="action_conv_flat")
                        self.action_fc = tf.keras.layers.Dense(board_width * board_width,activation=tf.nn.log_softmax)(self.action_conv_flat)
                        网络输出 胜率v值输出
                        # 4. v值输出
                        Y = tf.keras.layers.Conv2D(filters=1, kernel_size=[1, 1], padding="same", data_format="channels_last")(X)
                        Y = tf.keras.layers.BatchNormalization(epsilon=1e-5, fused=True)(Y)
                        Y = tf.nn.relu(Y)
                        self.evaluation_conv_flat = tf.reshape(Y, [-1, 1 * board_width * board_width], name="evaluation_conv_flat")
                        self.evaluation_fc1 = tf.keras.layers.Dense(64, activation='relu', name="evaluation_fc1")(self.evaluation_conv_flat)
                        self.evaluation_fc2 = tf.keras.layers.Dense(1, activation='tanh', name="evaluation_fc2")(self.evaluation_fc1)
                        打印出网络结构
                        self.model = tf.keras.Model(
                        inputs=[self.input_states],
                        outputs=[self.action_fc, self.evaluation_fc2])
                        self.model.summary()
                        损失函数计算和优化器
                        # 定义损失函数
                        # 1. P数组损失函数
                        #self.policy_loss = tf.keras.losses.CategoricalCrossentropy(from_logits=False)
                        # 2. v值损失函数
                        #self.value_loss = tf.keras.losses.MeanSquaredError()
                        # 3. L2正则项
                        #self.l2_penalty = tf.keras.metrics.MeanAbsoluteError()
                        # 4. 所有加起来成为损失函数
                        #self.loss = self.value_loss + self.policy_loss + self.l2_penalty
                        # 训练用的优化器
                        self.optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=self.learning_rate_fn, name="optimizer")
                        神经网络的输入是局面s,输出是预测的action概率向量p和胜率v,胜率是回归问题,优化自然用MSE损失,概率向量的优化要用softmax交叉熵损失,L2正则项是为了防止过拟合,目标就是最小化这个联合损失。就是让神经网络的预测跟MCTS的搜索结果尽量接近。
                        训练网络
                        def train_step(self, positions, pi, z, learning_rate=0.001):
                        with tf.GradientTape() as tape:
                        policy_head, value_head = self.model(positions, training=True)
                        loss = self.compute_loss(pi, z, policy_head, value_head)
                        metrics = self.compute_metrics(pi, policy_head)
                        grads = tape.gradient(loss, self.model.trainable_variables)
                        self.optimizer.apply_gradients(zip(grads, self.model.trainable_variables),global_step=self.global_step, name='train_step')
                        return loss, metrics
                        使用神经网络预测
                        def policy_value(self, state_batch):
                        state_batch=np.array(state_batch)
                        state_batch = state_batch.astype(np.float32)
                        if len(state_batch.shape) == 3:
                        sp = state_batch.shape
                        state_batch=np.reshape(state_batch, [1, sp[0], sp[1], sp[2]])
                        log_act_probs, value = self.model(state_batch, training=False)
                        act_probs = np.exp(log_act_probs) #OverflowError: Python int too large to convert to C long
                        return act_probs, value
                        现在神经网络部分全部完成。我们在下一篇实现一个人机对战的游戏界面,然后结合蒙特卡洛树搜索和神经网络估值实现AI交互。当然没有训练之前(他/她/它)的表现只能像个幼儿,后面就需要花费大量时间精力来刻意培养你的“小孩”了,训练好了就是人工智能,训练不好就变成人工智障了......。
                        AlphaZero代码实战系列 源代码打包
                        下载地址:https://download.csdn.net/download/askmeaskyou/12931806


                        IP属地:云南13楼2022-05-26 18:27
                        回复
                          后面的内容都发不了了,百度无故乱删,技术贴也发不出来。只能发广告了。
                          象棋菜刀是一款能连线多个中国象棋游戏平台并自动对弈的辅助工具。
                          从此你不必再去了解象棋软件越来越复杂的概念和设置(开局库、强机、强软、残局库、界面连线工具等等)。
                          只需要登陆游戏打开棋盘开始对弈,点击连线按钮就可以观赏行云流水的弈棋艺术,并享受到狂虐特大的快感。
                          记住功夫再高,也怕“菜刀”。
                          下载地址:https://cchess.lanzouv.com/b036syjmd 密码:123
                          QQ交流群:群名称:象棋菜刀群 号:979309477
                          软件使用交流可以在QQ群内讨论,整理后的帮助文档会发在百度贴吧。
                          贴吧地址: https://tieba.baidu.com/f?kw=象棋菜刀群
                          开通了微信公众号:xqcd321 微信公众号名称:象棋菜刀
                          微信公众号开通了手机拆棋,下棋的功能,手搬大师...
                          目前支持连线平台 天天象棋 QQ中国象棋2017 QQ新中国象棋 象棋微学堂网页版(王者象棋) 亦天棋缘 jj象棋 .....还在增加中。


                          IP属地:云南18楼2022-06-30 08:37
                          回复
                            象棋菜刀
                            是一款能连线各个游戏平台并自动对弈中国象棋网络游戏的辅助工具。
                            从此你不必再去了解象棋软件越来越复杂的概念和设置(开局库、强机、强软、残局库、界面连线工具等等)。
                            只需要登陆游戏打开棋盘开始对弈,点击连线按钮就可以观赏行云流水的弈棋艺术,并享受到狂虐特大的快感。
                            记住功夫再高,也怕“菜刀”。
                            官网:http://www.xqcd.top/
                            下载地址:https://cchess.lanzouv.com/b036syjmd 密码:123
                            QQ交流群:群名称:象棋菜刀群号:979309477
                            软件使用交流可以在QQ群内讨论,整理后的帮助文档会发在百度贴吧。
                            贴吧地址: https://tieba.baidu.com/f?kw=象棋菜刀群
                            开通了微信公众号:xqcd321 微信公众号名称:对弈菜刀
                            微信公众号开通了实战对弈(手搬大师)的功能,棋力跟电脑云端一致,方便手搬对战。


                            IP属地:云南19楼2023-01-06 22:59
                            回复