1. 程式人生 > >【自然語言處理】論述自然語言處理的技術範疇

【自然語言處理】論述自然語言處理的技術範疇

文章目錄

論述自然語言處理的技術範疇

一、前言

       本片博文主要是介紹說明自然語言處理的全貌,一些主要的技術範疇。
       自然語言處理(NLP)這個是一個很大的話題,,它是一個人機互動的一個過程,它涉及的學科比較廣泛譬如如下所示:

    1:語言學
    2:電腦科學(提供模型表示,演算法設計,計算機實現):
    3:當然還有數學以此來提供數學模型
    4:心理學(人類言語心理模型和理論)
    5:哲學(提供人類思維和語言的更高層次理論)
    6:統計學(提供樣本資料的預測統計技術)
    7:電子工程(資訊理論基礎和語言型號處理技術)
    8:生物學(人類言語行為機制理論)

       總之那涉及的學科範圍廣泛。不言而喻在自然語言處理研究工作中是十分艱難的,博主現在也只是學習它的一個小小的分支罷了,看到此篇博文的小夥伴希望能丟擲你們的建議和意見,要是如此博主甚是感激,開心呀!!!


二、主要技術範疇

1、語音合成(Speech Synthesis)

       所謂的語音合成就是指用人工的方式產生人類語音。語音合成器,就是利用計算機系統作用在語音合成上。而語音合成器可以用軟/硬體實現。
       文字轉語音(Text-To-Speech,TTS)系統則是將一般語言的文字轉換為語音,其他系統可以描繪語言符號的表示方式,就像音標轉換至語音一樣。
       語音合成器的質量: 通常取決於人聲的相似度及語義是否能被瞭解。舉個例子,對於個瞎子看不到文字,只能通過語音合成器很清楚的聽到文字轉換成語音的效果。
       語音合成的應用包括智慧儀表、智慧玩具、電子地圖、電子導遊、電子詞典等。

       總結:用大白話來講使用語音合成器可以實現文字轉換為語音,音標轉化為語音,並且效果如同非瞎看文字,瞎子聽語音同一個效果為最好。

2、語音識別(Speech Recognition)

       語音識別(Speech Recognition)技術也被稱為語音轉文字識別(Speech to Text,STT)目標是讓計算機自動將人類的語音內容轉換為相應的文字。
       語音識別技術的應用包括語音撥號、語音導航、室內裝置控制、語音文件檢索、簡單的聽寫資料錄入等。語音識別技術與其他自然語言處理技術如機器翻譯及語音合成技術相結合,可以構建出更加複雜的應用,例如,語音到語音的翻譯。
       總結:用大白話來講語音識別就是藉助計算機工具來識別人類說的話轉化為視覺化的東東(也就是文字啦)。

3、中文自動分詞

       中文自動分詞指的是----->使用計算機----->自動對中文文字----->進行詞語的切分。就像英文那樣使得中文句子中的詞之間有空格以標識。中文自動分詞也是中文自然語言處理中的 最底層的一個環節。
現有的方法:
       ⊚ 基於詞典的匹配:前向最大匹配、後向最大匹配。
       ⊚ 基於字的標註:最大熵模型、條件隨機場模型、感知器模型。
       ⊚ 其他方法:與詞性標註結合、與句法分析結合。

       例如以下是博主寫的一個簡單的測試
       程式碼

"""
 author:jjk
 datetime:2018/11/1
 coding:utf-8
 project name:Pycharm_workstation
 Program function: 中文分詞
                   結巴分詞
 
"""
import jieba # 匯入結巴分詞包
import jieba.posseg as pseg
import time #  時間

time_Start = time.time()

#f=open("t_with_splitter.txt","r")#讀取文字  
#string=f.read().decode("utf-8")

string = '中文自動分詞指的是使用計算機自動對中文文字進行詞語的切分,' + \
         '即像英文那樣使得中文句子中的詞之間有空格以標識。' + \
         '中文自動分詞被認為是中文自然語言處理中的一個最基本的環節'

words = pseg.cut(string) # 進行分詞
result = "" #記錄最終結果的變數 
for w in words:
    result += str(w.word) + "/" + str(w.flag) # 加詞性標註  
print(result) # 輸出結果
f = open("result.txt","w") #將結果儲存到另一個文件中 
f.write(result)
f.close()
time_Stop = time.time()
print("分詞及詞性標註完成,耗時:"+str(time_Stop-time_Start)+"秒。")# 輸出結果

       結果
在這裡插入圖片描述

4、詞性標註

       詞性標註(Part-of-Speech tagging 或POS tagging) 又稱詞類標註或者簡稱標註,是指在詞性標記集已確定,並且詞典中每個詞都有確定詞性的基礎上,將一個輸入詞串轉換成相應詞性標記串的過程。如上 3、中文自動分詞 中舉的例子的結果所示。
       在漢語中,因為漢語詞彙詞性多變的情況比較少見,大多詞語只有一個詞性,或者出現次最高的詞性遠遠高於第二位的詞性,相對比較簡單。同時,它也受到一些條件約束。比如:兼類詞在具體語境中的詞性判定問題、未登入詞即新詞詞性問題、兼類詞問題等。
       詞性標註方法包括概率方法、隱馬爾可夫模型的詞性標註方法、機器學習規則的方法等。

5、句法分析

  • 句法分析

       句法分析(Parsing)就是指對句子中的詞語語法功能進行分析。比如“歡迎大家使用演示平臺”就可以表示為"歡迎\VV 大家\PN 使用\VV 演示\NN 平臺\NN"。
       句法分析在中文資訊處理中的主要應用包括機器翻譯、命名實體識別等。

  • 自然語言生成

       自然語言生成研究使計算機具有人一樣的表達和寫作功能,即能夠根據一些關鍵資訊及其在機器內部的表達形式,經過一個規劃過程,自動生成一段高質量的自然語言文字。自然語言處理包括自然語言理解和自然語言生成自然語言生成是人工智慧和計算語言學的分支,相應的語言生成系統是基於語言資訊處理的計算機模型,其工作過程與自然語言分析相反,從抽象的概念層次開始,通過選擇並執行一定的語義和語法規則來生成文字。

6、文字分類

       文字分類用計算機對文字集按照一定的分類器模型進行自動分類標記。文字分類的總體過程如下(引用自 NLPIR 漢語分詞系統)。

(1) 預處理:將原始語料格式化為同一格式,便於後續的統一處理。
(2) 索引:將文件分解為基本處理單元,同時降低後續處理的開銷。
(3) 統計:詞頻統計,項(單詞、概念)與分類的相關概率。
(4) 特徵抽取:從文件中抽取出反映文件主題的特徵。
(5) 分類器:分類器的訓練。
(6) 評價:分類器的測試結果分析。

       文字分類常用演算法包括決策樹、樸素貝葉斯、神經網路、支援向量機、線性最小平方擬合、KNN、遺傳演算法、最大熵等,廣泛應用於垃圾過濾、新聞分類、詞性標註等。

7、文字挖掘

       文字挖掘一般指在文字處理過程中產生高質量的資訊。高質量的資訊通常通過分類和預測來產生,如模式識別。文字挖掘通常涉及輸入文字的處理過程,產生結構化資料,並最終評價和解釋輸出。
       例如博主的這篇文章中對微信朋友圈個性簽名生成詞雲的分析,就是一個文字挖掘。
       典型的文字挖掘方法包括文字分類、文字聚類、資訊抽取、概念/實體挖掘、情感分析和觀點分析等。

8、資訊抽取

       資訊抽取(Information Extraction)是從大量文字資料中自動為訪問資料庫而抽取特定訊息的技術
       簡單點來說從給定文字中抽取重要的資訊,比如時間、地點、人物、事件、原因、結果、數字、日期、貨幣、專有名詞等。大白話就是,就是要了解誰在什麼時候、什麼原因、對誰、做了什麼事、有什麼結果,涉及實體識別、時間抽取、因果關係抽取等關鍵技術。

9、 問答系統

       問答系統(Question Answering)是當下自然語言處理研究的熱點,也是未來自然語言處理的重點問題。從問答系統的外部行為來看,其與目前主流資訊檢索技術有兩點不同:首先是查詢方式為完整而口語化的問句,再者是其回傳的為高精準度網頁結果或明確的答案字串。
       至此不知道小夥伴你有沒有想到聊天機器人呀!!!

10、機器翻譯

       機器翻譯(Machine Translation,經常簡寫為MT)屬於計算語言學的範疇,是計算機程式將文字或演說從一種自然語言翻譯成另一種自然語言 。簡單來說,機器翻譯是通過將一個自然語言的字辭取代成另一個語言的字辭來實現的。藉由使用語料庫的技術,可達成更加複雜的自動翻譯,包闊可更佳地處理不同的文法結構、辭彙辨識、慣用語的對應等。
       這裡用博主自己的大白話的理解就是:將一種語言(比如中文) 翻譯成

11、文字情感分析

       文字情感分析(也稱為意見挖掘)是指用自然語言處理、文字挖掘及計算機語言學等方法來識別和提取原素材中的主觀資訊 。通常來說,情感分析的目的是為了找出說話者/作者在某些話題上或者針對一個文字兩極的觀點的態度。這個態度或許是他的個人判斷或評估,或許是他當時的情感狀態(也就是說,作者在做出這個言論時的情緒狀態),或是作者有意向的情感交流(就是作者想要讀者所體驗的情緒)等。
       總結:就是作者規定一些代表文字的態度詞,然後使用視覺化進行表現出來從而達到客戶情感交流。

12、自動摘要

       所謂自動摘要就是利用計算機自動地從原始文獻中提取文摘,文摘是全面準確地反映某一文獻中心內容的連貫短文。常用方法是自動摘要將文字作為句子的線性序列,將句子視為詞的線性序列。
       自動摘要可以按照技術型別和資訊提取分類。
       ⊚ 技術應用型別:自動提取給定文章的摘要資訊,自動計算文章中詞的權重,自動計算
文章中句子的權重。
       ⊚ 資訊提取:單篇文章的摘要自動提取,大規模文件的摘要自動提取,基於分類的摘要
自動提取。
       舉例如下所示:

"""
 author:jjk
 datetime:2018/10/15
 coding:utf-8
 project name:Pycharm_workstation
 Program function: 查詢關鍵詞
    思路:
	     1:載入已有的文件資料集
		 2:載入停用詞表
		 3:對資料集中的文件進行分詞
		 4:根據停用詞表,過來干擾詞
		 5:根據資料集訓練演算法


"""

import math
import jieba
import jieba.posseg as psg
from gensim import corpora, models
from jieba import analyse
import functools
import numpy as np


# 停用詞載入方法
def get_stopword_list():
    stop_word_path = './data/stopword.txt'
    # 遍歷txt文件,剔除''
    stopword_list = [sw.replace('\n', '') for sw in open(stop_word_path, encoding='utf-8').readlines()]
    return stopword_list


# 分詞方法,呼叫結巴介面
# pos是判斷是否採用詞性標註的引數
def seg_to_list(sentence, pos=False):
    if not pos:
        # 不進行詞性標註的分詞方法
        seg_list = jieba.cut(sentence)
    else:
        # 進行詞性標註的分詞方法
        seg_list = psg.cut(sentence)
    return seg_list


# 去除干擾詞,根據pos判斷是否過濾除名詞外的其他詞性,再判斷詞是否在停用詞表中,長度是否大於等於2等。
def word_filter(seg_list, pos=False):
    stopword_list = get_stopword_list()
    filter_list = []
    # 根據pos引數選擇是否詞性過濾
    # 不進行詞性過濾,則將詞性都標記為n,表示全部保留
    for seg in seg_list:
        if not pos:
            word = seg
            flag = 'n'
        else:
            word = seg.word
            flag = seg.flag
        if not flag.startswith('n'):
            continue
        # 過濾高停用詞表中的詞,以及長度為<2的詞
        if not word in stopword_list and len(word) > 1:
            filter_list.append(word)
    return filter_list


# 資料載入
# corpus.txt為資料集
def load_data(pos=False, corpus_path='./data/corpus.txt'):
    # 呼叫上面 方式對資料集進行處理,處理之後的資料集僅保留非干擾詞
    doc_list = []
    for line in open(corpus_path, 'rb'):
        content = line.strip()
        seg_list = seg_to_list(content, pos)
        filter_list = word_filter(seg_list, pos)
        doc_list.append(filter_list)
    return doc_list


# idf值統計方法
def train_idf(doc_list):
    idf_dic = {}
    # 總文件數
    tt_count = len(doc_list)
    # 每個詞出現的文件數
    for doc in doc_list:
        for word in set(doc):
            idf_dic[word] = idf_dic.get(word, 0.0) + 1.0

    # 按公式轉換為idf值,分母加1進行平滑處理
    for k, v in idf_dic.items():
        idf_dic[k] = math.log(tt_count / (1.0 + v))
    # 對於沒有在字典中的詞,預設其盡在一個文件出現,得到預設idf值
    default_idf = math.log(tt_count / (1.0))
    return idf_dic, default_idf


# topK
# cmp()函式是為了輸出top關鍵詞時,先按照關鍵詞的計算分值排序,在得分相同時,根據關鍵詞進行排序時
def cmp(e1, e2):
    # import numpy as np
    res = np.sign(e1[1] - e2[1])
    if res != 0:
        return res
    else:
        a = e1[0] + e2[0]
        b = e2[0] + e1[0]
        if a > b:
            return 1
        elif a == b:
            return 0
        else:
            return -1


# TF-IDF類
class TfIdf(object):
    # 訓練好的idf字典,預設idf值,處理後的待提取文字,關鍵詞數量
    def __init__(self, idf_dic, default_idf, word_list, keyword_num):
        self.word_list = word_list
        self.idf_dic, self.default_idf = idf_dic, default_idf
        self.tf_dic = self.get_tf_dic()
        self.keyword_num = keyword_num

    # 統計tf值
    def get_tf_dic(self):
        tf_dic = {}
        for word in self.word_list:
            tf_dic[word] = tf_dic.get(word, 0.0) + 1.0
        tt_count = len(self.word_list)
        for k, v in tf_dic.items():
            tf_dic[k] = float(v) / tt_count
        return tf_dic

    # 按公式計算tf-idf
    def get_tfidf(self):
        tfidf_dic = {}
        for word in self.word_list:
            idf = self.idf_dic.get(word, self.default_idf)
            tf = self.tf_dic.get(word, 0)
            tfidf = tf * idf
            tfidf_dic[word] = tfidf
        # 根據tf-idf排序,取排名前keyword_num的詞作為關鍵詞
        for k, v in sorted(tfidf_dic.items(), key=functools.cmp_to_key(cmp), reverse=True)[:self.keyword_num]:
            print(k + "/", end='')
        print()


# 主題模型
class TopicModel(object):
    #
    def __init__(self, doc_list, keyword_num, model="LSI", num_topics=4):
        # 使用gensim介面,將文字轉為向量化表示
        self.dictionary = corpora.Dictionary(doc_list)
        # 使用BOW模型向量化
        corpus = [self.dictionary.doc2bow(doc) for doc in doc_list]
        # 對每個詞,根據tf-idf進行加權,得到加權後的向量表示
        self.tfidf_model = models.TfidfModel(corpus)
        self.corpus_tfidf = self.tfidf_model[corpus]

        self.keyword_num = keyword_num
        self.num_topics = num_topics
        # 選擇載入的模型
        if model == 'LSI':
            self.model = self.train_lsi()
        else:
            self.model = self.train_lda()
        # 得到資料集的主題-詞分佈
        word_dic = self.word_dictionary(doc_list)
        self.wordtopic_dic = self.get_wordtopic(word_dic)

    def train_lsi(self):
        lsi = models.LsiModel(self.corpus_tfidf, id2word=self.dictionary, num_topics=self.num_topics)
        return lsi

    def train_lda(self):
        lda = models.LdaModel(self.corpus_tfidf, id2word=self.dictionary, num_topics=self.num_topics)
        return lda

    def get_wordtopic(self, word_dic):
        wordtopic_dic = {}
        for word in word_dic:
            single_list = [word]
            wordcorpus = self.tfidf_model[self.dictionary.doc2bow(single_list)]
            wordtopic = self.model[wordcorpus]
            wordtopic_dic[word] = wordtopic
        return wordtopic_dic

    # 詞空間構建方法和向量化方法,在沒有gensim介面時的一般處理方法
    def word_dictionary(self, doc_list):
        dictionary = []
        for doc in doc_list:
            dictionary.extend(doc)

        dictionary = list(set(dictionary))

        return dictionary

    def doc2bowvec(self, word_list):
        vec_list = [1 if word in word_list else 0 for word in self.dictionary]
        return vec_list

    # 計算詞的分佈和文件的分佈的相似度,取相似度最高的keyword_num個詞作為關鍵詞
    def get_simword(self, word_list):
        sentcorpus = self.tfidf_model[self.dictionary.doc2bow(word_list)]
        senttopic = self.model[sentcorpus]

        # 餘弦相似度計算
        def calsim(l1, l2):
            a, b, c = 0.0, 0.0, 0.0
            for t1, t2 in zip(l1, l2):
                x1 = t1[1]
                x2 = t2[1]
                a += x1 * x1
                b += x1 * x1
                c += x2 * x2
            sim = a / math.sqrt(b * c) if not (b * c) == 0.0 else 0.0
            return sim

        # 計算輸入文字和每個詞的主題分佈相似度
        sim_dic = {}
        for k, v in self.wordtopic_dic.items():
            if k not in word_list:
                continue
            sim = calsim(v, senttopic)
            sim_dic[k] = sim

        for k, v in sorted(sim_dic.items(), key=functools.cmp_to_key(cmp), reverse=True)[:self.keyword_num]:
            print(k + "/ ", end='')
        print()


def tfidf_extract(word_list, pos=False, keyword_num=10):
    doc_list = load_data(pos)
    idf_dic, default_idf = train_idf(doc_list)
    tfidf_model = TfIdf(idf_dic, default_idf, word_list, keyword_num)
    tfidf_model.get_tfidf()


def textrank_extract(text, pos=False, keyword_num=10):
    textrank = analyse.textrank
    keywords = textrank(text, keyword_num)
    # 輸出抽取出的關鍵詞
    for keyword in keywords:
        print(keyword + "/")


# print()

def topic_extract(word_list, model, pos=False, keyword_num=10):
    doc_list = load_data(pos)
    topic_model = TopicModel(doc_list, keyword_num, model=model)
    topic_model.get_simword(word_list)


if __name__ == '__main__':
    # 獲取測試文字
    text1 = 'test.txt'
    text = open(text1, encoding='utf-8').read()
    print(text)

    pos = True
    seg_list = seg_to_list(text, pos)
    filter_list = word_filter(seg_list, pos)

    print('\nTF-IDF模型結果:')
    tfidf_extract(filter_list)

    print('\nTextRank模型結果:')
    textrank_extract(text)

    print('\nLSI模型結果:')
    topic_extract(filter_list, 'LSI', pos)

    print('\nLDA模型結果:')
    topic_extract(filter_list, 'LDA', pos)

       結果
在這裡插入圖片描述

13、文字蘊涵

       文字蘊涵(Textual Entailment,TE)
       文字蘊涵在自然語言處理中主要指一個文字片段之間的定向關係。
       ⊚ 正向蘊涵
       文字T:日本時間2011 年3 日11 日,日本宮城縣發生里氏震級9.0 震,造成死傷失蹤約3 萬多人。
       假設H:日本時間2011 年3 日11 日,日本宮城縣發生里氏震級9.0 強震。
       ⊚ 矛盾蘊涵
       文字T:張學友在1961 年7 月10 日,生於香港,祖籍天津。
       假設H:張學友生於1960 年。
       ⊚ 獨立蘊涵
       文字T:黎姿與“殘障富豪”馬廷強結婚。
       假設H:馬廷強為香港“東方報業集團”創辦人之一馬惜如之子。

三、自然語言處理的難點

1、語言環境複雜

       自然語言處理的語言環境較為複雜,以命名實體識別進行分析,對於同一個漢字某些情況下可以看作實體處理,某些情況則不能看作實體。
       例如,天龍八部中的“竹劍”小姐姐 在有些情況下可能就是指的是竹子做得劍。還有“湖北” 有可能指定是地點 “湖北”,也有可能指定是“湖的北邊”。可見字自然語言處理過程中語言環境(根據上下文才能究其表達的意思)的複雜。

2、文字結構形式多樣

       文字內部結構形式多樣。還是以自然語言處理中的命名實體識別任務為例子,例如:
       ⊚ 人名,人名由姓和名構成。其中姓氏包括單姓和複姓(如趙、錢、孫、李、慕容、東方、西門等),名由若干個漢字組成。姓氏的用字範圍相對有限,比較容易識別。然而名就比較靈活,既可以用名、字、號表示,也可以使用職務名和用典。比如:“李白、李十二、李翰林、李供奉、李拾遺、李太白、青蓮居士,謫仙人”都是同一個人。
       ⊚ 地名一般由若干個字組成地名,可以為作為字尾關鍵字或者別名,都是指代一個地方。比如:“成都、蓉城、錦城、芙蓉城、錦官城、天府之國”,其中“蓉城、錦城、芙蓉城、錦官城、天府之國”為別名。除了全稱的名稱,還有地理位置代表地名的。比如:“河南、河南省、豫”都是指的一個省份,其中“豫”是簡稱。
       ⊚ 組織機構名,組織機構命名方式比較複雜,有些是修飾性的命名,有些表示歷史典故,有些表示地理方位,有些表示地名,有些表示風俗習慣和關鍵字等。例如:組織名“廣州恆大淘寶足球俱樂部”中,“廣州”表示地名的成分,“恆大”“淘寶”表示公司名稱成分,“足球”是一項體育賽事成分,“俱樂部”是關鍵字的成分。比如:“四川大