閒着無聊的時候,我就會問問自己,編程也有了五年經驗了,除了增刪改查,我還會什麼,有一天我跳槽,去面試的時候,我能比那些年輕而且期望薪資待遇低的年輕畢業生,我有什麼優勢,而且我只是一個專科的機電系學生,居然來做軟件編程,好戲劇的一切,漸漸的給自己洗腦,自己都忘記自己是培訓機構出來的,説了這麼多抱怨的話,沒有説培訓機構的不好,沒有説我們專科生就一定比高學歷人才的差,歸根到底還是需要學習吧,自學了半年多python,現在報了一個假期培訓班來學習NLP,英語是硬傷,自己表示很無奈。

  言歸正傳,我來給大家分享一下,我這這段時間學到了什麼(2019-06-15至2019-07-01)。

  既然我們選擇了人工智能,我們就應該知道什麼是人工智能,什麼是NLP,我們先來明確這個幾個名詞吧。

 [1]  2017年12月,人工智能入選“2017年度中國媒體十大流行語”。(百度摘取)

  在我這,我認為,人工智能就是希望讓我們現有的設備(比如計算機,機器人)來幫助人們做更多的事,並且可以賦予人類的思想,人類的理性和人類的行為的機器。比如我們現在的智能停車場,語音客服,工廠的自動機器人等等。

NLP是神經語言程序學(Neuro-Linguistic Programming)的英文縮寫。一般被成為自然語言處理,在我這認為NLP主要是就是讓機器可以賦予人類語言正常交流並且賦予人類思想的功能。比如聊天機器人,比如新聞分類,垃圾郵件處理。

  我們知道中文的語法比較多,我們先來一個最簡單的,生成一句話。現有一個文本,大致為

host = """
host = 時間名詞 主語名詞 形容詞 動詞 事務名詞
時間名詞 = 上午、下午、昨天、晌午、半夜、去年、明天
主語名詞 = 學生、羣眾、老頭、婦女、同志、叔叔
形容詞 = 很快地、迅速地、悄悄地、靜靜地
動詞 = 打、追着、敲着、吆喝、盯着
事務名詞 = 蝸牛、獵豹、奧托、棒球、戰鬥機、冥王星
"""

我們可以看到,文本的第一行為一個句子的元素都有什麼,時間名詞+主語+(形容詞)+動詞+(事務名詞)可以構成一句話,比如,今晚我們要狠狠的加班。也可以為,明天領導請我們吃大餐。

所有我們在上述文本中按照時間名詞+主語+(形容詞)+動詞+(事務名詞)的格式可以組成任意的語句(別考慮有的通不通順的問題),下面我們來看一下代碼的實現。

思路,1-得到文本,2-按照行來切割,3-得到句子元素格式,4-隨機從下面的元素集取值,5-按照格式來拼接成句子。

代碼:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import random

host = """
host = 時間名詞 主語名詞 形容詞 動詞 事務名詞
時間名詞 = 上午、下午、昨天、晌午、半夜、去年、明天
主語名詞 = 學生、羣眾、老頭、婦女、同志、叔叔
形容詞 = 很快地、迅速地、悄悄地、靜靜地
動詞 = 打、追着、敲着、吆喝、盯着
事務名詞 = 蝸牛、獵豹、奧托、棒球、戰鬥機、冥王星
"""


# 該方法主要是將文本轉換成字典類型的數據
def create_grammar(grammar_str, split='=', line_split='\n', code_split='、'):
    grammar = {}
    for line in grammar_str.split(line_split):
        if line is '':
            continue
        k, v = line.split(split)
        grammar[k.strip()] = [s.split() for s in v.split(code_split)]
    return grammar


# 隨機選擇
choice = random.choice


# 得到句子
def generate(gram, target):
    if target not in gram:
        return target
    else:
        li = choice(gram[target])
        sentence = ''  # 最終的句子
        aa = [generate(gram, t) for t in li]
        for s in aa:
            if s is not '/n':
                sentence += s
        return sentence


if __name__ == '__main__':
    for i in range(10):
        adj = generate(create_grammar(host, '='), target='host')
        print(adj)

運行後,我們會發現很多句子是錯的,完全不符合我們的講話習慣,所以我們這樣的隨機選擇並不是明智的選擇,我們接下來處理這個不明智選擇問題,讓他盡力做到可以按照人類講話方式來輸出‘固定格式’的話。

  下面我來做個小遊戲,也是電視節目中常見的,給予提示,讓你猜出詞語,比如金罐、上火;我們大多數人會第一想到加多寶,比如,我們説教室、黑色,我們會想到黑板;再比如,下午,6點,我們會想到加班。還有等等,也是人類根據前面給予的詞語,會立即給予一個反應。這個也就是我最近學到的N-gram

  N-gram模型是一種語言模型(Language Model,LM),語言模型是一個基於概率的判別模型,它的輸入是一句話(單詞的順序序列),輸出是這句話的概率,即這些單詞的聯合概率(joint probability)。

  N-Gram是基於一個假設:第n個詞出現與前n-1個詞相關,而與其他任何詞不相關(這也是隱馬爾可夫當中的假設)。整個句子出現的概率就等於各個詞出現的概率乘積。各個詞的概率可以通過語料中統計計算得到。通常N-Gram取自文本或語料庫。N=1時稱為unigram,N=2稱為bigram,N=3稱為trigram,假設下一個詞的出現依賴它前面的一個詞,即 bigram,假設下一個詞的出現依賴它前面的兩個詞,即 trigram,以此類推。理論上,n 越大越好,經驗上,trigram 用的最多,儘管如此,原則上,能用 bigram 解決,絕不使用 trigram。

  我們先來看幾個公式:

  1-gram: P(w1, w2, w3, … , wn)=P(w1)P(w2|w1)P(w3|w1w2)P(w4|w1w2w3)…P(wn|w1w2…wn-1)≈P(w1)P(w2|w1)P(w3|w2)P(w4|w3)…P(wn|wn-1)

  2-gram:P(w1, w2, w3, … , wn)=P(w1)P(w2|w1)P(w3|w1w2)P(w4|w1w2w3)…P(wn|w1w2…wn-1)≈P(w1)P(w2|w1)P(w3|w1w2)P(w4|w2w3)…P(wn|wn-2wn-1)

  大概來解釋一下是什麼,P(w1)就是w1在語料庫內出現的概率,也就是count(w1)/ total;P(w2|w1)是w2出現在w1後面的概率,也就是説 count(w1w2)/count(w2);我們再用2-gram來看一個實際的例子。

我們喜歡看書,切詞以後變為 我們、喜歡、看、書,這時變為P(我們,喜歡,看,書)=p(我們)p(喜歡|我們)p(看|我們,喜歡)p(書|喜歡,看)

  p(我們)表示“我們”這個詞在語料庫裏面出現的概率;

   p(喜歡|我們)表示“喜歡”這個詞出現在“大家”後面的概率;(出現《我們》詞語的次數當作分母,出現《我們喜歡》詞語的次數當作分子)

 

   p(看|我們,喜歡)表示“看”這個詞出現在“我們喜歡”後面的概率;(出現《我們喜歡》的次數當作分母,出現《我們喜歡看》的次數當作分子)

 

   p(書|喜歡,看)表示“書”這個詞出現在“我們喜歡看”後面的概率。(出現《喜歡看》的次數當作分母,出現《喜歡看書》當作分子)

  

  以此類推,我們用2-gram時,只考慮其前面兩個詞語就可以了。

 

  然後他們的乘積我們會得到一個0-1的數字,無限趨近於0表示這個語句很有可能是錯的,無限趨近於1的時候表示這個語句很有可能是對的

 

  代碼實現還沒完成。最近工作煩心事比較多,代碼寫了一部分,還沒有完全弄完的。過幾天會補上。