自学围棋的alphago

关注:5 发布时间:2021-07-26 20:47:01

导语本文整理了自学围棋的alphago经验知识,帮助您全面了解,小白也能成为高手,跟随小编一起来看一看吧!

遥想当年,alphago的掌握版本,在完胜柯洁九段之后不久,就被后辈alphago zero(简称狗零)击溃了。

从一只完全不懂围棋的ai,到打败大师,狗零只用了21天。

而且,它不需要用人类知识来喂养,成为棋手全靠自学。

如果能培育这样一只ai,即便自己不会下棋,也可以很骄傲吧。

于是,来自巴黎的少年dylan djian(简称小笛) ,就照着狗零的论文去实现了一下。

他给自己的人工智能棋手起名supergo,也提供了代码(传送门见文底) 。

除此之外,还有教程——

一个身子两个头

智能体分成三个部分:

一是特征提取器(特征提取器),二是策略网络(政策网络),三是价值网络(价值网络).

于是,狗零也被亲切地称为"双头怪"。特征提取器是身子,其他两个网络是脑子。

特征提取器

特征提取模型,是个残差网络(resnet),就是给普通美国有线电视新闻网加上了跳层连接(跳过连接),让梯度的传播更加通畅。

跳跃的样子,写成代码就是:

1clasbasicblock(nn .模块):

2 """

3具有2个卷积和一个跳跃连接的基本剩余块

四在比较后一次线性单元激活之前。

5 """

6

7def__init__(自,平面内,平面,步幅=1,下采样=无):

8 super(基本锁定,自锁定).__init__

9

10 self.conv1=nn .conv2d(平面,平面,内核大小=3,

11步幅=步幅,填充=1,偏差=假)

12 self.bn1=nn .batchnorm2d(平面)

13

14 self.conv2=nn .conv2d(平面,平面kernel_size=3,

15步幅=步幅,填充=1,偏差=假)

16 self.bn2=nn .batchnorm2d(平面)

17

18

19defforward(self,x):

20残差=x

21

22 out=self.conv1(x)

23 out=f.relu(self.bn1(out))

24

25 out=self.conv2(out)

26 out=self.bn2(out)

27

28输出=剩余

29 out=f.relu(out)

30

31返回

然后,把它加到特征提取模型里面去:

一类提取器(nn .模块):

2def__init__(自身、输入、输出):

3超级(提取器,自)。__init__

4 self.conv1=nn .conv2d(输入平面,输出平面,步幅=1,

5内核_大小=3,填充=1,偏差=假)

6 self.bn1=nn .batchnorm2d(输出通道)

8forblockinrange(blocks):

9 setattr(self," res{} " .格式(块),\

10基本锁定(输出通道,输出通道))

11

12

13前进(自我,x):

14 x=f . relu(self。bn 1(自我。con v1(x)))

15 for blockinrange(blocks-1):

16 x=getattr(self," { res } " .格式(块))(x)

17

18 feature_maps=getattr(self," { res } " .格式(blocks - 1))(x)

19returnfeature _ maps

策略网络

策略网络就是普通的美国有线电视新闻网了,里面有个批量标准化(批量标准化),还有一个全连接层,输出概率分布。

1类政策网(nn .模块):

2def__init__(自身、输入、输出):

3超级(policynet,self).__init__

4自我。输出通道=输出通道

5 self.conv=nn .con v2d(平面内,1,kernel_size=1)

6 self.bn=nn .batchnom2d(1)

7 self.logsoftmax=nn .logsoftmax(dim=1)

8 self.fc=nn .线性(输出通道- 1,输出通道)

9

10

11前进(自我,x):

12 x=f.relu(self.bn(self.conv(x)))

13 x=x.view(-1,self。输出通道-1)

14 x=self.fc(x)

15 probas=self.logsoftmax(x).exp

16

17returnprobas

价值网络

这个网络稍微复杂一点。除了标配之外,还要再多加一个全连接层。比较后,用双曲正切(双曲正切)算出(-1,1) 之间的数值,来表示当前状态下的赢面多大。

代码长这样——

1clasvaluenet(nn .模块):

2def__init__(自身、输入、输出):

3 super(valuenet,self).__init__

4自我。输出通道=输出通道

5 self.conv=nn .con v2d(平面内,1,kernel_size=1)

6 self.bn=nn .batchnom2d(1)

7 self.fc1=nn .线性(输出通道- 1,256)

8 self.fc2=nn .线性(256,1)

9

10

11前进(自我,x):

12 x=f.relu(self.bn(self.conv(x)))

13 x=x.view(-1,self。输出通道-1)

14 x=f.relu(self.fc1(x))

15 winding=f . tanh(self . fc2(x))

16returnwinning

未雨绸缪

狗零的另一个重要组成部分是蒙特卡洛树搜索(mcts)。

它允许ai玩家提前找出胜率比较高的地方。

在模拟器中,对手的下一手牌是模拟的,下一手牌是给的,所以远远一步多。

节点

树上的每个节点代表不同的情况,并具有不同的统计数据:

每个节点已经通过的次数n,总动作值w,通过这个点的先验概率p,平均动作值q (q=w/n),从其他地方来到这个节点的步骤,以及从这个节点开始的所有可能的后续步骤。

1classnode:

2def__init__(自身,父项=无,proba=无,move=无):

3 self.p=proba

4 self.n=0

5 self.w=0

6 self.q=0

7 self.children=[]

8 self.parent=家长

9 .移动=移动

卷展栏(卷展栏)

第一步是puct(多项式上的置信树)算法,该算法选择能够比较大化puct函数的变体的行走方法(如下)。

用代码写的,——

1选择(节点,c_puct=c_puct):

2“基于puct公式选择的优化版本”

4 total_count=0

5 foriirange(nodes . shape[0]):

6 total_count=nodes[i][1]

8 action _ scores=np . zeros(nodes . shape[0])

9 forinrange(nodes . shape[0]):

10 action _ scores[i]=nodes[i][0]c _ puct * nodes[i][2]* \

11 (np.sqrt(total_count)/(1个节点[i][1])

12

13等于=np . where(action _ scores==np . max(action _ scores))[0]

14ifequals.shape[0] 0:

15returnnp.random.choice(等于)

16returnequal

s[0]

结束(结束)

选择在不停地进行,直至到达一个叶节点(叶节点),而这个节点还没有往下生枝。

1defis_leaf(self):

2 """检查节点是否为叶" " "

3

4 returnlen(self。儿童)=0

到了叶节点,那里的一个随机状态就会被评估,得出所有"下一步"的概率。

所有被禁的落子点,概率会变成零,然后重新把总概率归为1。

然后,这个叶节点就会生出枝节(都是可以落子的位置,概率不为零的那些) 。代码如下——

1defexpand(self,probas):

2自我。子节点=[节点(父节点=自身,移动=idx,proba=probas[idx]) \

3 foridxinnrange(probas。形状[0])if probas[idx]0]

更新一下

枝节生好之后,这个叶节点和它的妈妈们,身上的统计数据都会更新,用的是下面这两串代码。

1defupdate(self,v):

2 """在展示后更新节点统计信息" " "

3

4 self.w=self.w v

5自我。q=self。w/self。nif self。n 0 else 0

1whilecurrent_node.parent:

2 current_node.update(v)

3电流_节点=电流_节点。父母

选择落子点

模拟器搭好了,每个可能的"下一步",都有了自己的统计数据。

按照这些数据,算法会选择其中一步,真要落子的地方。

选择有两种,一就是选择被模拟的次数比较多的点。试用于测试和实战。

另外一种,随机(随机)选择,把节点被经过的次数转换成概率分布,用的是以下代码——

一总计=np.sum(action_scores)

2 probas=action_scores/total

3移动=np。随机。选择(动作分数。shape[0],p=probas)

后者适用于训练,让阿尔法围棋探索更多可能的选择。

三位一体的修炼

狗零的修炼分为三个过程,是异步的。

一是自对弈(自玩),用来生成数据。

1defself_play:

2whiletrue:

3新_玩家,检查点=load_player

4ifnew_player:

5玩家=新_玩家

6

7 ##创建进程的自运行匹配队列

8个结果=create_matches(player,cores=parallel_self_play,

9 match_number=self_play_match)

10 for _ in范围(self _ play _ match):

11 result=results.get

12 db.insert({

13 "游戏" :结果,

14 "id":游戏id(_ d)

15 })

16 game_id=1

二是训练(培训),拿新鲜生成的数据,来改进当前的神经网络。

1deftrain:

2标准=alphaloss

3数据集=自交数据集

四播放器,检查点=load_player(current_time,loaded_version)

5 optimizer=create _ optimizer(player,lr,

6参数=检查点["优化器"])

7 best_player=deepcopy(player)

8 dataloader=dataloader(数据集,collate_fn=collate_fn,\

9批处理大小=批处理大小,洗牌=真)

10

11whiletrue:

12forbatch_idx,(state,move,winner)in numerate(data loader):

13

14 # # #评估当前网络的副本

15 if total _ ite % train _ steps==0:

16 pending_player=deepcopy(播放器)

17结果=评估(待定_玩家,比较佳_玩家)

18

19ifresult:

20比较佳玩家=待定玩家

21

22示例={

23 "state": state,

24 "winner": winner,

25 "移动" :移动

26 }

27 optimizer.zero_grad

28赢家,probas=pending_player.predict(示例["state"])

29

30损失=标准(获胜者,例如["获胜者"],\

31 probas,示例["移动"])

32亏损。倒退

33 optimizer.step

34

35 ##取新游戏

36 if total _ ite % refresh _ tick==0:

37 last_id=fetch_new_games(集合,数据集,last_id)

训练用的损失函数表示如下:

一类丢失(torch.nn.module):

2def__init__(self):

3超级(阿尔法损失,自我).__init__

5defforward(self,pred_winner,winner,pred_probas,probas):

6 value _ error=(winner-pred _ winner)* * 2

7策略_错误=torch。sum((-probas *

8 (1e-6 pred_probas).log),1)

9 total _ error=(value _ error。视图(-1)策略_错误).平均值

10returntotal_error

第三个是评估受过训练的代理是否比生成数据的代理更好(比较佳人选返回第一步并继续生成数据)。

1defevaluate(player,new_player):

2结果=玩(玩家,对手=新_玩家)

3个black_wins=0

4 white_wins=0

6forresultinresults:

7ifresult[0]==1:

8个white_wins=1

9elifresult[0]==0:

10个black_wins=1

11

12 # # #检查受训玩家(黑)是否优于

13 ##当前比较佳玩家取决于门槛

14ifblack_wins=eval_thresh * len(结果):

15返回真

16returnfalse

第三部分很重要。只有不断选择比较佳网络生成高质量数据,才能提高ai的棋艺。

只有重复这三个环节,才能培养出一个强有力的棋手。

对ai go感兴趣的人也可以试试这个pytorch实现。

比较初取自量子位,原dylan djian。

代码实现门户:

网页链接

教程原始门户:

网页链接

alphago零论文门户:

网页链接

猜你喜欢

热门互联网经验

360微商频道查询入口