iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 24
2
AI & Data

深入淺出搜尋引擎和自然語言處理系列 第 24

Day 24: Hangman猜字遊戲和訓練集處理

距離完成我的三十天鐵人賽剩下最後的七篇文章了。我打算用一個遊戲--Hangman猜字遊戲來結束這個系列。昨天說到語言模型,語言模型可以以字詞為單位作N-gram,也可以以字母為單位。最後這個系列就要以語言模型為底層技術來寫一個猜字遊戲的AI。

猜字遊戲Hangman

Hangman game的玩法是透過一個人寫下一個字,讓另一個人來猜。對方一次會猜一個英文字母,猜對的話就把字母寫到正確的格子上,猜錯的話則會記錄下來。若是猜錯的次數達到一個數字,則猜字的一方輸。

這裡我們先開發一個簡易版:

def hangman(secret_word, guesser, max_mistakes=8, verbose=True, **guesser_args):
    """
        secret_word是將要被猜的字、guesser是我們之後會陸續寫進來的猜字模型(真人猜字或AI)、max_mistakes是最多可以錯誤的次數、
        verbose為True時表示互動性猜字(AI猜字時可以改False)、guesser_args是一個keyword argument。
    """
    secret_word = secret_word.lower()
    mask = ['_'] * len(secret_word) # 把要被猜的字轉成暗文
    guessed = set()
    if verbose:
        print("開始猜字遊戲,提示:", ' '.join(mask), '長度為', len(secret_word))
    
    mistakes = 0
    while mistakes < max_mistakes:
        if verbose:
            print("你還有", (max_mistakes-mistakes), "次機會。")
        guess = guesser(mask, guessed, **guesser_args)

        if verbose:
            print('你猜了:', guess)
        if guess in guessed:
            if verbose:
                print('這個字母已經猜過了!')
            mistakes += 1
        else:
            guessed.add(guess)
            if guess in secret_word:
                for i, c in enumerate(secret_word):
                    if c == guess:
                        mask[i] = c
                if verbose:
                    print('猜對了,', ' '.join(mask))
            else:
                if verbose:
                    print('抱歉,再猜猜')
                mistakes += 1
                
        if '_' not in mask:
            if verbose:
                print('恭喜你贏了!')
            return mistakes
        
    if verbose:
        print('沒有機會了,正確字是', secret_word)    
    return mistakes

這裡我們先寫一個人機互動猜字版:

def human(mask, guessed, **kwargs):
    """
    可以手動遊玩
    """
    print('請輸入你要猜的字:')
    return input().lower().strip()

interactive = True

試玩遊戲:

if interactive:
    hangman('algorithm', human, 8, True)

https://ithelp.ithome.com.tw/upload/images/20190925/20118683pwdk7xO5az.png

準備訓練和測試集

開始寫我們的AI猜字之前,要先準備訓練集和測試集。從這篇文章中可以看到,照著統計學來猜字是個不錯的做法,因此我們也自己來訓練一組模型,照著出現的頻率為順序進行猜字。

我們使用之前用過的Brown Corpus來訓練AI猜字演算法,為了刻意增加猜字的難度,AI在測試時的字和訓練的字會是不一樣的(把訓練集和測試集拆開),如此才能訓練出更通用的模型。

我們使用 nltk.corpus.Brown 裡的 words() 方法,從中將非英文字母的文字去除,同時將每個字小寫化。之後,我們用 numpy.random.shuffle 來隨機刷取文集中的字,以分成訓練集和測試集。測試集裡有1000字,剩下的字都會到訓練集裡面。

from nltk.corpus import brown
import numpy as np

np.random.seed(12345)

# word_set 儲存Brown Corpus中所有獨特的字型
word_set = []
# test_set 儲存1000個字的測試集
test_set = []
# training_set 將剩下的字存到訓練集中
training_set = []


word_s = set([])

for word in brown.words():
    if word.isalpha():
        word = word.lower()
        if word not in word_s:
            word_s.add(word)

word_set = list(word_s)
np.random.shuffle(word_set)

test_set = word_set[:1000]
training_set = word_set[1000:]

print(len(word_set))
print(len(test_set))
print(len(training_set))

這裡一來就不是一個人寫一個字讓對方猜了,而是電腦和人類的對決:

if interactive:
    hangman(np.random.choice(test_set), human, 8, True)

大家可以自己玩玩看~今天的Jupyter Notebook在這裏


上一篇
Day 23: 語言是有跡可循的!關於語言模型
下一篇
Day 25: 三種AI猜字方法
系列文
深入淺出搜尋引擎和自然語言處理30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言