位置:首页游戏数码>自学围棋的AlphaGo Zero,你也可以造一个 自学围棋的好处?

自学围棋的AlphaGo Zero,你也可以造一个 自学围棋的好处?

所属分类:游戏数码 发布时间:2025/8/16 12:24:29

01

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

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

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

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

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

他给自己的AI棋手起名SuperGo,也提供了代码(传送门见文底) 。

除此之外,还有教程

一个身子两个头

智能体分成三个部分:

一是特征提取器(Feature Extractor) ,二是策略网络(Policy Network) ,三是价值网络(Value Network) 。

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

特征提取器

特征提取模型,是个残差网络 (ResNet) ,就是给普通CNN加上了跳层连接 (Skip Connection) , 让梯度的传播更加通畅。

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

1classBasicBlock(nn.Module):

2 """

3 Basic residual block with 2 convolutions and a skip connection

4 before the last ReLU activation.

5 """

6

7def__init__(self, inplanes, planes, stride=1, downsample=None):

8 super(BasicBlock, self).__init__()

9

10 self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=3,

11 stride=stride, padding=1, bias=False)

12 self.bn1 = nn.BatchNorm2d(planes)

13

14 self.conv2 = nn.Conv2d(planes, planes, kernel_size=3,

15 stride=stride, padding=1, bias=False)

16 self.bn2 = nn.BatchNorm2d(planes)

17

18

19defforward(self, x):

20 residual = 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 out += residual

29 out = F.relu(out)

30

31returnout

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

1classExtractor(nn.Module):

2def__init__(self, inplanes, outplanes):

3 super(Extractor, self).__init__()

4 self.conv1 = nn.Conv2d(inplanes, outplanes, stride=1,

5 kernel_size=3, padding=1, bias=False)

6 self.bn1 = nn.BatchNorm2d(outplanes)

7

8forblockinrange(BLOCKS):

9 setattr(self, "res{}".format(block), \

10 BasicBlock(outplanes, outplanes))

11

12

13defforward(self, x):

14 x = F.relu(self.bn1(self.conv1(x)))

15forblockinrange(BLOCKS - 1):

16 x = getattr(self, "res{}".format(block))(x)

17

18 feature_maps = getattr(self, "res{}".format(BLOCKS - 1))(x)

19returnfeature_maps

策略网络

策略网络就是普通的CNN了,里面有个批量标准化(Batch Normalization) ,还有一个全连接层,输出概率分布。

1classPolicyNet(nn.Module):

2def__init__(self, inplanes, outplanes):

3 super(PolicyNet, self).__init__()

4 self.outplanes = outplanes

5 self.conv = nn.Conv2d(inplanes, 1, kernel_size=1)

6 self.bn = nn.BatchNorm2d(1)

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

8 self.fc = nn.Linear(outplanes - 1, outplanes)

9

10

11defforward(self, x):

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

13 x = x.view(-1, self.outplanes - 1)

14 x = self.fc(x)

15 probas = self.logsoftmax(x).exp()

16

17returnprobas

价值网络

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

代码长这样

1classValueNet(nn.Module):

2def__init__(self, inplanes, outplanes):

3 super(ValueNet, self).__init__()

4 self.outplanes = outplanes

5 self.conv = nn.Conv2d(inplanes, 1, kernel_size=1)

6 self.bn = nn.BatchNorm2d(1)

7 self.fc1 = nn.Linear(outplanes - 1, 256)

8 self.fc2 = nn.Linear(256, 1)

9

10

11defforward(self, x):

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

13 x = x.view(-1, self.outplanes - 1)

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

15 winning = F.tanh(self.fc2(x))

16returnwinning

未雨绸缪的树

狗零,还有一个很重要的组成部分,就是蒙特卡洛树搜索(MCTS) 。

它可以让AI棋手提前找出,胜率最高的落子点。

在模拟器里,模拟对方的下一手,以及再下一手,给出应对之策,所以提前的远不止是一步。

节点 (Node)

树上的每一个节点,都代表一种不同的局势,有不同的统计数据:

每个节点被经过的次数n,总动作值w,经过这一点的先验概率p,平均动作值q (q=w/n) ,还有从别处来到这个节点走的那一步,以及从这个节点出发、所有可能的下一步。

1classNode:

2def__init__(self, parent=None, proba=None, move=None):

3 self.p = proba

4 self.n = 0

5 self.w = 0

6 self.q = 0

7 self.children = []

8 self.parent = parent

9 self.move = move

部署 (Rollout)

第一步是PUCT (多项式上置信树) 算法,选择能让PUCT函数 (下图) 的某个变体 (Variant)最大化,的走法。

写成代码的话

1defselect(nodes, c_puct=C_PUCT):

2 " Optimized version of the selection based of the PUCT formula "

3

4 total_count = 0

5foriinrange(nodes.shape[0]):

6 total_count += nodes[i][1]

7

8 action_scores = np.zeros(nodes.shape[0])

9foriinrange(nodes.shape[0]):

10 action_scores[i] = nodes[i][0] + c_puct * nodes[i][2] * \

11 (np.sqrt(total_count) / (1 + nodes[i][1]))

12

13 equals = np.where(action_scores == np.max(action_scores))[0]

14ifequals.shape[0] > 0:

15returnnp.random.choice(equals)

16returnequals[0]

结束 (Ending)

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

1defis_leaf(self):

2 """ Check whether a node is a leaf or not """

3

4returnlen(self.children) == 0

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

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

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

1defexpand(self, probas):

2 self.children = [Node(parent=self, move=idx, proba=probas[idx]) \

3foridxinrange(probas.shape[0])ifprobas[idx] > 0]

更新一下

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

1defupdate(self, v):

2 """ Update the node statistics after a rollout """

3

4 self.w = self.w + v

5 self.q = self.w / self.nifself.n > 0else0

1whilecurrent_node.parent:

2 current_node.update(v)

3 current_node = current_node.parent

选择落子点

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

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

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

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

1 total = np.sum(action_scores)

2 probas = action_scores / total

3 move = np.random.choice(action_scores.shape[0], p=probas)

后者适用于训练,让AlphaGo探索更多可能的选择。

三位一体的修炼

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

一是自对弈(Self-Play) ,用来生成数据。

1defself_play():

2whileTrue:

3 new_player, checkpoint = load_player()

4ifnew_player:

5 player = new_player

6

7 ## Create the self-play match queue of processes

8 results = create_matches(player, cores=PARALLEL_SELF_PLAY,

9 match_number=SELF_PLAY_MATCH)

10for_inrange(SELF_PLAY_MATCH):

11 result = results.get()

12 db.insert({

13 "game": result,

14 "id": game_id

15 })

16 game_id += 1

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

1deftrain():

2 criterion = AlphaLoss()

3 dataset = SelfPlayDataset()

4 player, checkpoint = load_player(current_time, loaded_version)

5 optimizer = create_optimizer(player, lr,

6 param=checkpoint['optimizer'])

7 best_player = deepcopy(player)

8 dataloader = DataLoader(dataset, collate_fn=collate_fn, \

9 batch_size=BATCH_SIZE, shuffle=True)

10

11whileTrue:

12forbatch_idx, (state, move, winner)inenumerate(dataloader):

13

14 ## Evaluate a copy of the current network

15iftotal_ite % TRAIN_STEPS == 0:

16 pending_player = deepcopy(player)

17 result = evaluate(pending_player, best_player)

18

19ifresult:

20 best_player = pending_player

21

22 example = {

23 'state': state,

24 'winner': winner,

25 'move' : move

26 }

27 optimizer.zero_grad()

28 winner, probas = pending_player.predict(example['state'])

29

30 loss = criterion(winner, example['winner'], \

31 probas, example['move'])

32 loss.backward()

33 optimizer.step()

34

35 ## Fetch new games

36iftotal_ite % REFRESH_TICK == 0:

37 last_id = fetch_new_games(collection, dataset, last_id)

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

1classAlphaLoss(torch.nn.Module):

2def__init__(self):

3 super(AlphaLoss, self).__init__()

4

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

6 value_error = (winner - pred_winner) ** 2

7 policy_error = torch.sum((-probas *

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

9 total_error = (value_error.view(-1) + policy_error).mean()

10returntotal_error

三是评估(Evaluation) ,看训练过的智能体,比起正在生成数据的智能体,是不是更优秀了 (最优秀者回到第一步,继续生成数据) 。

1defevaluate(player, new_player):

2 results = play(player, opponent=new_player)

3 black_wins = 0

4 white_wins = 0

5

6forresultinresults:

7ifresult[0] == 1:

8 white_wins += 1

9elifresult[0] == 0:

10 black_wins += 1

11

12 ## Check if the trained player (black) is better than

13 ## the current best player depending on the threshold

14ifblack_wins >= EVAL_THRESH * len(results):

15returnTrue

16returnFalse

第三部分很重要,要不断选出最优的网络,来不断生成高质量的数据,才能提升AI的棋艺。

三个环节周而复始,才能养成强大的棋手。

有志于AI围棋的各位,也可以试一试这个PyTorch实现。

本来摘自量子位,原作 Dylan Djian。

代码实现传送门:

网页链接

教程原文传送门:

网页链接

AlphaGo Zero论文传送门:

网页链接

推荐信息

  • AlphaGo的神奇全靠它,详解人工神经网络! alphago fan

    游戏数码时间:2025/8/12 5:28:29

    01Alphago在不被看好的情况下,以4比1击败了围棋世界冠军李世石,令其名震天下。随着AlphaGo知名度的不断提高,人们不禁好奇,究竟是什么使得AlphaGo得以战胜人类大脑?AlphaGo的核心依托人工神经网络。什么是神经网络?人工神经网络是一种模仿生物神经网络(动物的中枢神经系统,特别是大

  • 100:0,新AlphaGo放弃了人类? alpha官网

    游戏数码时间:2025/8/20 19:48:02

    012017年10月19日,谷歌子公司DeepMind发布了AlphaGo的新版本。很多人知道AlpoaGo是一个人工智能程序,却不知道它其实是一个家族,早期战胜韩国选手李世石的是AlphaGo Lee。在乌镇击败世界冠军柯洁的是AlphaGo Master。本次发布的是AlphaGo Zero(阿

  • 这是迄今为止,AlphaGo算法最清晰的解读! 这是迄今为止最全的追女生秘籍了

    游戏数码时间:2025/8/16 22:56:45

    012016年DeepMind团队(google旗下)的AlphaGo(一个围棋的AI)以4:1战胜顶尖人类职业棋手李世石。她到底是怎么下棋的?AlphaGo在面对当前棋局时,她会模拟(推演棋局)N次,选取“模拟”次数最多的走法,这就是AlphaGo认为的最优走法。例如图中,

  • 大尺度美剧排行榜前十名 大尺的美剧

    游戏数码时间:2025/8/20 17:56:49

    现在网络越来越发达了,所以很多朋友喜欢看美剧,比如:老友记、丧尸国都等等,一些美剧确实让我们打开眼界学了不少东西,但是有些美剧却尺度很大,让人惊讶。一起来看看大尺度美剧排行榜前十名。操作方法01蛇蝎美人每一集都是一个单独的故事,而且故事的主题都是美丽女子看着自身魅力来复仇,每一集都有尺度很大的激情画

  • 喜剧片排行榜前十名 喜剧片排行榜前十名豆瓣

    游戏数码时间:2025/8/22 0:27:30

    喜剧电影一般情况下观看的人数很多,大家平时工作压力大一般情况下放松的话都会去电影院看喜剧电影让自己开怀大笑,今天就一起看下喜剧片排行榜前十名。操作方法01《四十岁的老处男》这部电影围绕着安迪,他将近40岁,在他的生活中从未发生过性行为,他在一场扑克游戏中向他的朋友透露了他的秘密,然后他所有的朋友都开

  • 丧尸片排行榜前十名 亚洲丧尸片排行榜前十名

    游戏数码时间:2025/8/14 4:20:29

    最近几年无论是国内还是国外关于丧失的电影上映了不少,可能是人类对未知事物的恐惧?我们在观看丧失电影的时候除了害怕更多的确实刺激吧。今天就一起盘点下丧尸片排行榜前十名。操作方法01《死灵狩》在日本,四名珠宝窃贼抢劫了一家珠宝店,然后前往一家废弃的工厂,他们计划在那里把这些商品卖给黑帮,不幸的是,他们所

  • 十大微电影排行榜 微电影最好看的

    游戏数码时间:2025/8/20 12:49:50

    假期周末闲暇之际,看一场好看的电影,放松心情,酷知网小编为大家整理了值得一看的十大微电影排行榜单哦。操作方法011.《双世青蛇》(古装爱情片)简介:白蛇私配凡人,犯下天条,镇于雷峰塔下,青蛇遭受牵连被打入寒冰界洛川河遭受雷霆诛心之苦。洛川河上渡人魂魄往生的神使寻崖,救了青蛇但三百年后自己天劫将至,面

  • 悬疑电影排行榜前十名世界排名 豆瓣评分9.0以上的悬疑电影

    游戏数码时间:2025/8/20 13:51:50

    悬疑电影一直是很多影迷的追求,通常情况下悬疑电影比较烧脑,看电影离开一分钟可能就不知道后面演的什么玩意了,并且这类电影不看几遍根本想不出所以然,就是因为这种费劲的感觉吸引着大批的人。今天就来欣赏下悬疑电影排行榜前十名世界排名。操作方法01心慌方和上面的题材差不多,都是悬疑类型,的主人公为了解决内心疑

  • 韩国女明星排行榜前十名 韩国女明星榜单

    游戏数码时间:2025/8/16 23:38:25

    大家都知道韩国这个国家虽然不大,但是整形和美女却非常的有名。在这里重点要说的就是女明星了,不仔细看以为韩国女明星都是一个模样复制的。今天就来盘点下韩国女明星排行榜前十名。操作方法01韩孝周是韩国最美女星之一,因在韩国电视剧《非常特别的客人》和《同伊》中扮演主角而闻名。这位30岁的女演员凭借在电视剧和

  • 最好看的穿越剧排行榜前十名 最好看的穿越剧排行榜前十名鞠婧怡

    游戏数码时间:2025/8/23 2:35:07

    随着影视业的不断发展,我们现在市面上有着很多类型的电视剧,比如:谍战、古装、喜剧等等,如果说这好玩的恐怕就是穿越剧了,今天就一起看看最好看的穿越剧排行榜前十名。操作方法01这里的寻秦记可不是最新版本的,是古天乐版本。这一版本可以称得上真正的经典,不仅里面演员颜值在线,演技也是不遑多让的,主要讲的是主