• 懂視移動端 視頻1 視頻21 視頻41 視頻61 視頻文章1 視頻文章21 視頻文章41 視頻文章61 視頻擴展1 視頻擴展6 視頻擴展11 視頻擴展16 文章1 文章201 文章401 文章601 文章801 文章1001 資訊1 資訊501 資訊1001 資訊1501 標簽1 標簽501 標簽1001 關鍵詞1 關鍵詞501 關鍵詞1001 關鍵詞1501
    當前位置: 首頁 - 養生常識 - 正文

    自學圍棋的AlphaGo Zero,你也可以造一個

    來源:懂視網 責編:小OO 時間:2020-10-06 22:15:14
    導讀遙想當年,AlphaGo的Master版本,在完勝柯潔九段之后不久,就被后輩AlphaGo Zero?(簡稱狗零) 擊潰了。從一只完全不懂圍棋的AI,到打敗Master,狗零只用了21天。而且,它不需要用人類知識來喂養,成為頂尖棋手全靠自學。如果能培育這樣一只AI,即便自己不會下棋,也可以很驕傲吧。于是,來自巴黎的少年Dylan Djian (簡稱小笛) ,就照著狗零的論文去實現了一下。他給自己的AI棋手起名SuperGo,也提供了代碼?(傳送門見文底) 。除此之外,還有教程——一個身子兩個頭智...

    遙想當年,AlphaGo的Master版本,在完勝柯潔九段之后不久,就被后輩AlphaGo Zero?(簡稱狗零) 擊潰了。

    從一只完全不懂圍棋的AI,到打敗Master,狗零只用了21天。

    而且,它不需要用人類知識來喂養,成為頂尖棋手全靠自學。

    如果能培育這樣一只AI,即便自己不會下棋,也可以很驕傲吧。

    于是,來自巴黎的少年Dylan Djian (簡稱小笛) ,就照著狗零的論文去實現了一下。

    他給自己的AI棋手起名SuperGo,也提供了代碼?(傳送門見文底) 。

    除此之外,還有教程——

    一個身子兩個頭

    智能體分成三個部分:

    一是特征提取器?(Feature Extractor) ,二是策略網絡?(Policy Network) ,三是價值網絡(Value Network) 。

    于是,狗零也被親切地稱為“雙頭怪”。特征提取器是身子,其他兩個網絡是腦子。

    特征提取器

    特征提取模型,是個殘差網絡 (ResNet) ,就是給普通CNN加上了跳層連接 (Skip Connection) , 讓梯度的傳播更加通暢。

    跳躍的樣子,寫成代碼就是:

    1class?BasicBlock(nn.Module):

    2 """

    3 Basic residual block with 2 convolutions and a skip connection

    4 before the last ReLU activation.

    5 """

    7?def?__init__(self, inplanes, planes, stride=1, downsample=None):

    8 super(BasicBlock, self).__init__()

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

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

    12 self.bn1 = nn.BatchNorm2d(planes)

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

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

    16 self.bn2 = nn.BatchNorm2d(planes)

    19?def?forward(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

    31?return?out

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

    1class?Extractor(nn.Module):

    2?def?__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)

    8?for?block?in?range(BLOCKS):

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

    10 BasicBlock(outplanes, outplanes))

    13?def?forward(self, x):

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

    15?for?block?in?range(BLOCKS - 1):

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

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

    19?return?feature_maps

    策略網絡

    策略網絡就是普通的CNN了,里面有個批量標準化?(Batch Normalization) ,還有一個全連接層,輸出概率分布。

    ?

    1class?PolicyNet(nn.Module):

    2?def?__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)

    11?def?forward(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()

    17?return?probas

    價值網絡

    這個網絡稍微復雜一點。除了標配之外,還要再多加一個全連接層。最后,用雙曲正切 (Hyperbolic Tangent) 算出 (-1,1) 之間的數值,來表示當前狀態下的贏面多大。

    代碼長這樣——

    1class?ValueNet(nn.Module):

    2?def?__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)

    11?def?forward(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))

    16?return?winning

    未雨綢繆的樹

    狗零,還有一個很重要的組成部分,就是蒙特卡洛樹搜索?(MCTS) 。

    它可以讓AI棋手提前找出,勝率最高的落子點。

    在模擬器里,模擬對方的下一手,以及再下一手,給出應對之策,所以提前的遠不止是一步。

    節點 (Node)

    樹上的每一個節點,都代表一種不同的局勢,有不同的統計數據:

    每個節點被經過的次數n,總動作值w,經過這一點的先驗概率p,平均動作值q (q=w/n) ,還有從別處來到這個節點走的那一步,以及從這個節點出發、所有可能的下一步。

    1class?Node:

    2?def?__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)?最大化,的走法。

    ?寫成代碼的話——

    1def?select(nodes, c_puct=C_PUCT):

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

    4 total_count = 0

    5?for?i?in?range(nodes.shape[0]):

    6 total_count += nodes[i][1]

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

    9?for?i?in?range(nodes.shape[0]):

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

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

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

    14?if?equals.shape[0] > 0:

    15?return?np.random.choice(equals)

    16?return?equals[0]

    結束 (Ending)

    選擇在不停地進行,直至到達一個葉節點 (Leaf Node) ,而這個節點還沒有往下生枝。

    1def?is_leaf(self):

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

    4?return?len(self.children) == 0

    到了葉節點,那里的一個隨機狀態就會被評估,得出所有“下一步”的概率。

    所有被禁的落子點,概率會變成零,然后重新把總概率歸為1。

    然后,這個葉節點就會生出枝節 (都是可以落子的位置,概率不為零的那些) 。代碼如下——

    1def?expand(self, probas):

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

    3?for?idx?in?range(probas.shape[0])?if?probas[idx] > 0]

    更新一下

    枝節生好之后,這個葉節點和它的媽媽們,身上的統計數據都會更新,用的是下面這兩串代碼。

    1def?update(self, v):

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

    4 self.w = self.w + v

    5 self.q = self.w / self.n?if?self.n > 0?else?0

    1while?current_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) ,用來生成數據。

    1def?self_play():

    2?while?True:

    3 new_player, checkpoint = load_player()

    4?if?new_player:

    5 player = new_player

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

    8 results = create_matches(player, cores=PARALLEL_SELF_PLAY,

    9 match_number=SELF_PLAY_MATCH)

    10?for?_?in?range(SELF_PLAY_MATCH):

    11 result = results.get()

    12 db.insert({

    13 "game": result,

    14 "id": game_id

    15 })

    16 game_id += 1

    二是訓練?(Training) ,拿新鮮生成的數據,來改進當前的神經網絡。

    1def?train():

    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)

    11?while?True:

    12?for?batch_idx, (state, move, winner)?in?enumerate(dataloader):

    14 ## Evaluate a copy of the current network

    15?if?total_ite % TRAIN_STEPS == 0:

    16 pending_player = deepcopy(player)

    17 result = evaluate(pending_player, best_player)

    19?if?result:

    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

    36?if?total_ite % REFRESH_TICK == 0:

    37 last_id = fetch_new_games(collection, dataset, last_id)

    訓練用的損失函數表示如下:

    1class?AlphaLoss(torch.nn.Module):

    2?def?__init__(self):

    3 super(AlphaLoss, self).__init__()

    5?def?forward(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()

    10?return?total_error

    三是評估?(Evaluation) ,看訓練過的智能體,比起正在生成數據的智能體,是不是更優秀了 (最優秀者回到第一步,繼續生成數據) 。

    1def?evaluate(player, new_player):

    2 results = play(player, opponent=new_player)

    3 black_wins = 0

    4 white_wins = 0

    6?for?result?in?results:

    7?if?result[0] == 1:

    8 white_wins += 1

    9?elif?result[0] == 0:

    10 black_wins += 1

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

    13 ## the current best player depending on the threshold

    14?if?black_wins >= EVAL_THRESH * len(results):

    15?return?True

    16?return?False

    第三部分很重要,要不斷選出最優的網絡,來不斷生成高質量的數據,才能提升AI的棋藝。

    三個環節周而復始,才能養成強大的棋手。

    有志于AI圍棋的各位,也可以試一試這個PyTorch實現。

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

    代碼實現傳送門:

    網頁鏈接

    教程原文傳送門:

    網頁鏈接

    AlphaGo Zero論文傳送門:

    網頁鏈接

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:0731-84117792 E-MAIL:11247931@qq.com

    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    最美逆行者!基層女干部在一線發來抗疫宣言 急救車女司機:與疫情“賽跑”的日子 疫情中常提的“葉欣”是誰?背后故事令人淚目 疫情下最有溫度的3種女人,比“消毒水”還管用 疫情當頭,這四個女人出名了 “00后”志愿者女生:戰“疫”沒有假期 誰說女子不如男,“疫”線警花別樣綻放 “疫情不除,頭發不留”,90后女就是這么剛! 是巾幗,更是勇士!致敬穿著白衣戰袍的她們! “戰疫日記”,致敬抗疫一線巾幗紅! 春節從初一到十五的講究忌諱,你知道多少? 關于春節祝福語大全,一份祝福送親友! 大年初一拜年原來這么多講究,千萬別錯了! 門炮仗,拜年,壓歲錢...正月初一的傳統習俗知多少? 春節是怎么來的?古代也有春節嗎?! 春節:是一年之歲首,傳統意義上的年節 關于除夕的對聯,寫一副讓新年有新氣象! 除夕當天,應該怎么做才最吉利呢? 除夕祝福語大全,新年鐘聲敲響送上好寓意! 帶你了解除夕,"中國年"的特殊文化符號! 不打不相識,職業棋手與AI“化敵為友” 圍棋人機戰五大謠言,第4局谷歌放水? 當年的人機大戰:柯潔到底輸了多少? 繼象棋之后,人機大戰為何選中圍棋? 人機大戰團隊賽對人不公平?李世乭很生氣! 圍棋“人機大戰”打響人工智能或搶醫生飯碗? 【回憶殺】人機大戰精彩瞬間 復盤人機大戰首局—無可奈可的半目勝負 人工智能失禮?圍觀人機大戰你該知道的圍棋禮儀 人工智能如何實現人臉識別,你不知道的奧秘 5G和物聯網的火熱,正驅動AI芯片由云端走向邊端 賦能全場景應用,海量數據需要AI與IoT融合 可怕!8億人的工作崗位將被AI替代 區塊鏈和人工智能:完美匹配 前世今生,帶你了解AlphaGo的發展歷程 [愚人節] 愚人節不可愚的五大基本原則 西班牙愚人節為什么叫神圣無辜者節? 4.1日愚人節這天開玩笑只能到中午12點,你知道嗎? 愚人節表白的回答,愚人節表白短信 愚人節整人方法,愚人節整人方法大全
    Top
    亚洲大尺度无码无码专区_亚洲精品中文字幕无码AV_大陆国产国语对白视频_国模GOGO中国人体私拍