<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          數(shù)據(jù)分析入門(mén)系列教程-貝葉斯實(shí)戰(zhàn)

          共 1790字,需瀏覽 4分鐘

           ·

          2020-11-19 00:49


          樸素貝葉斯分類(lèi)最適合的場(chǎng)景就是文本分類(lèi)了,無(wú)論是情感分析還是文檔分類(lèi)及垃圾郵件識(shí)別,都是樸素貝葉斯最為擅長(zhǎng)的地方,其也成為了自然語(yǔ)言處理 NLP 方向的重要工具。

          文本到向量

          既然說(shuō)到了 NLP,那么就不得不提及從文本到向量的轉(zhuǎn)換。我們都知道,計(jì)算機(jī)是比較擅長(zhǎng)處理數(shù)字類(lèi)型的數(shù)據(jù)的,而對(duì)于字符類(lèi)型數(shù)據(jù)往往都需要轉(zhuǎn)換成數(shù)字類(lèi)型,再進(jìn)行相關(guān)運(yùn)算。在自然語(yǔ)言處理領(lǐng)域同樣如此,拿到文本后,我們需要先把文本轉(zhuǎn)化成向量,然后再做處理。

          為現(xiàn)在較為流行的文本轉(zhuǎn)向量的方式有兩種,詞袋和詞頻逆文檔。在應(yīng)用這兩種方式的時(shí)候,都是需要有一個(gè)詞典庫(kù)的。這個(gè)就相當(dāng)于,如果你想分析金融領(lǐng)域的文本,那么這個(gè)詞典庫(kù)中包含的單詞就應(yīng)該是與金融相關(guān)的;如果你想分析教育領(lǐng)域的文本,那么詞典庫(kù)應(yīng)該是與教育相關(guān)的。

          為了方便起見(jiàn),我這里設(shè)置一個(gè)簡(jiǎn)單的詞典庫(kù)如下

          詞典庫(kù) [“我們”,“跑步”,“早飯”,“吃”,"去","出發(fā)","早上"]

          詞袋模型

          詞袋模型又可以理解為 count vector,就是查看詞典庫(kù)中的詞語(yǔ)出現(xiàn)在文本中的次數(shù),出現(xiàn)幾次就標(biāo)注為數(shù)字幾

          文本1:早上去跑步

          文本2:我們吃早飯去跑步

          文本3:我們出發(fā)吃早飯我們跑步

          首先把三個(gè)文件進(jìn)行單詞分割,可以表示成如下形式:

          文本1:早上|去|跑步

          文本2:我們|吃|早飯|去|跑步

          文本3:我們|出發(fā)|吃|早飯|我們|跑步

          下面就可以查看各個(gè)文本中出現(xiàn)詞庫(kù)里單詞的數(shù)量了

          文本1:

          早上去跑步
          (0,1,0,0,1,0,1)

          文本2:

          我們吃早飯去跑步
          (1,1,1,1,1,0,,0)

          文本3:

          我們出發(fā)吃早飯我們跑步
          (2,1,1,1,0,1,0)

          至此,通過(guò)詞袋模型,我們已經(jīng)成功的將一個(gè)文本,轉(zhuǎn)換成了向量的形式。

          當(dāng)然也可以看到詞袋模型的缺點(diǎn),它拋棄了文檔中的前后邏輯,語(yǔ)義結(jié)構(gòu)等信息,僅僅以詞語(yǔ)出現(xiàn)的次數(shù)作為評(píng)判標(biāo)準(zhǔn)。

          正是為了解決這一缺點(diǎn),又出現(xiàn)了詞頻逆文檔模型(TF-IDF)

          詞頻逆文檔

          詞頻逆文檔又稱(chēng)為 TF-IDF,TF 就是詞頻的意思,為 IDF 則為逆向文檔頻率的意思。

          TF:計(jì)算一個(gè)單詞在文檔中出現(xiàn)的頻次

          IDF:指一個(gè)單詞在文檔中的區(qū)分度,該模型認(rèn)為一個(gè)單詞出現(xiàn)的文檔數(shù)越少,則越能夠通過(guò)該單詞區(qū)分不同的文檔,IDF 越大就代表單詞的區(qū)分度越高。

          計(jì)算方式:

          TF = 單詞出現(xiàn)的次數(shù)/該文檔的總單詞數(shù)

          IDF = log(文檔總數(shù)/該單詞出現(xiàn)的文檔數(shù)+1)

          TF-IDF = TF * IDF

          這樣你應(yīng)該可以看出,一些出現(xiàn)頻率很高的指向詞,比如你我他等,雖然 TF 會(huì)很高,但是 IDF 的值會(huì)很低,所以它們的 TF-IDF 值也不高。而我們通過(guò)經(jīng)驗(yàn)也可以知道,通過(guò)你我他這些詞是很難區(qū)分不同文檔的,即它們的重要性比較低。

          情感分析

          本節(jié)所有的數(shù)據(jù)集到保存在 GitHub 上

          https://github.com/zhouwei713/DataAnalyse/tree/master/Naive_Bayes

          下面我們就開(kāi)始進(jìn)入今天的實(shí)戰(zhàn)部分,首先來(lái)看一個(gè)例子,根據(jù)用戶(hù)評(píng)論,分析是正向評(píng)論還是負(fù)向評(píng)論。

          我們先來(lái)看下語(yǔ)料庫(kù)

          分別是停用詞,測(cè)試數(shù)據(jù)集,訓(xùn)練數(shù)據(jù)集(負(fù)向評(píng)論和正向評(píng)論)

          停用詞:在文本分析領(lǐng)域,一般都會(huì)把一些經(jīng)常出現(xiàn)的但是又沒(méi)有實(shí)際意思或者不影響語(yǔ)義的詞語(yǔ)去除掉,就是停用詞

          測(cè)試數(shù)據(jù)集:我們看下它長(zhǎng)什么樣子

          標(biāo)簽中的就是測(cè)試數(shù)據(jù),而 label 則表示該評(píng)論的正負(fù)向,能夠看出1是正向的,0是負(fù)向的。

          訓(xùn)練集:

          數(shù)據(jù)格式也是類(lèi)似的,文本保存在標(biāo)簽當(dāng)中。

          提取文本

          我們首先要做的就是對(duì)語(yǔ)料庫(kù)做處理,提取出我們需要的文本內(nèi)容

          我們先處理測(cè)試集數(shù)據(jù)

          with?open('sentiment/test.txt',?'r',?encoding='utf-8')?as?f:
          ????reviews,?labels?=?[],?[]
          ????start?=?False
          ????for?file?in?f:
          ????????file?=?file.strip()
          ????????if?not?file:
          ????????????continue
          ????????if?file.startswith(")?and?not?start:
          ????????????start?=?True
          ????????????if?"label"?in?file:
          ????????????????labels.append(file.split('"')[3])
          ????????????continue
          ????????if?start?and?file?==?r"":
          ????????????start?=?False
          ????????????continue
          ????????if?start:
          ????????????reviews.append(file)????print(reviews,?labels)

          通過(guò) with 函數(shù)打開(kāi)文件,初始化兩個(gè)列表 reviews 和 labels,分別用來(lái)保存評(píng)論內(nèi)容和對(duì)用的 label。
          start = False 用來(lái)做判斷,控制是否開(kāi)始評(píng)論內(nèi)容
          file = file.strip() 去除字符串中的空格
          file.startswith("file.split('"')[3] 切分字符串,并去除第4個(gè)原始(腳標(biāo)從0開(kāi)始)

          接著再來(lái)處理訓(xùn)練集數(shù)據(jù),由于訓(xùn)練集數(shù)據(jù)和測(cè)試集數(shù)據(jù)格式非常類(lèi)似,我們可以把上面的代碼做些修改,改寫(xiě)成函數(shù)供后面調(diào)用

          def?load_data(file,?is_positive=None):
          ????reviews,?labels?=?[],?[]
          ????with?open(file,?'r',?encoding='utf-8')?as?f:
          ????????start?=?False
          ????????review_text?=?[]
          ????????for?file?in?f:
          ????????????file?=?file.strip()
          ????????????if?not?file:
          ????????????????continue
          ????????????if?file.startswith(")?and?not?start:
          ????????????????start?=?True
          ????????????????if?"label"?in?file:
          ????????????????????labels.append(int(file.split('"')[3]))
          ????????????????continue
          ????????????if?start?and?file?==?r"":
          ????????????????start?=?False
          ????????????????reviews.append("?".join(review_text))
          ????????????????review_text?=?[]
          ????????????????continue
          ????????????if?start:
          ????????????????review_text.append(file)
          ????if?is_positive:
          ????????labels?=?[1]?*?len(reviews)
          ????elif?is_positive?==?False:
          ????????labels?=?[0]?*?len(reviews)

          ????return?reviews,?labels

          整體沒(méi)有太多變化,只是增加了標(biāo)簽的管理。

          下面再寫(xiě)一個(gè)函數(shù),把訓(xùn)練集合并起來(lái)

          def?process_file():
          ????train_pos_file?=?"sentiment/train.positive.txt"
          ????train_neg_file?=?"sentiment/train.negative.txt"
          ????test_comb_file?=?"sentiment/test.txt"

          ????#?讀取文件部分,把具體的內(nèi)容寫(xiě)入到變量里面
          ????train_pos_cmts,?train_pos_lbs?=?load_data(train_pos_file,?True)
          ????train_neg_cmts,?train_neg_lbs?=?load_data(train_neg_file,?False)
          ????train_comments?=?train_pos_cmts?+?train_neg_cmts
          ????train_labels?=?train_pos_lbs?+?train_neg_lbs
          ????test_comments,?test_labels?=?load_data(test_comb_file)
          ????return?train_comments,?train_labels,?test_comments,?test_labels

          可以簡(jiǎn)單查看下訓(xùn)練數(shù)據(jù)

          print(len(train_comments),?len(test_comments))
          print(train_comments[3],?train_labels[3])
          >>>
          8064?2500
          先付款的???有信用?1

          數(shù)據(jù)預(yù)處理

          下面可以進(jìn)行一些簡(jiǎn)單的數(shù)據(jù)預(yù)處理,把文本中的中文字符和數(shù)字處理掉,并去掉停用詞

          def?deal_text(text,?stop_path):
          ????stopwords?=?set()
          ????with?open(stop_path,?'r',?encoding='utf-8')?as?in_file:
          ????????for?line?in?in_file:
          ????????????stopwords.add(line.strip())

          ????text?=?re.sub('[!!]+',?"!",?text)
          ????text?=?re.sub('[??]+',?"?",?text)
          ????text?=?re.sub("[a-zA-Z#$%&\'()*+,-./:;:<=>@,。★、…【】《》“”‘’[\\]^_`{|}~]+",?"?UNK?",?text)
          ????text?=?re.sub(r"\d+",?'?NUM?',?text)
          ????text?=?re.sub(r"\s+",?"?",?text)??
          ????text?=?"?".join([term?for?term?in?jieba.cut(text)?if?term?and?not?term?in?stopwords])
          ????return?text
          train_comments_new?=?[deal_text(comment,?"sentiment/stopwords.txt")?for?comment?in?train_comments]
          test_comments_new?=?[deal_text(comment,?"sentiment/stopwords.txt")?for?comment?in?test_comments]print(train_comments_new[0],?test_comments_new[0])
          >>>
          發(fā)短信?特別?不?方便 ! 背后?屏幕?很大?起來(lái)?不?舒服?? UNK ??手觸?屏 ! 切換?屏幕?很?麻煩 ! 終于?找到?同道中人?初中?? UNK ??已經(jīng)?喜歡?上?? UNK ??同學(xué)?都?鄙夷?眼光?看?? UNK ??人為?? UNK ??樣子?古怪?說(shuō)?"?丑?"?當(dāng)場(chǎng)?氣暈?現(xiàn)在?同道中人?? UNK ??好開(kāi)心 ! ? UNK ? ! ? UNK ?

          用到了正則表達(dá)式,我們?cè)诘谝还?jié) Python 基礎(chǔ)課中已經(jīng)介紹過(guò)了
          還用到了 jieba 分詞庫(kù),這里重點(diǎn)介紹下

          jieba 分詞庫(kù)

          jieba 分詞庫(kù)是中文語(yǔ)言處理中非常常用的分詞工具,現(xiàn)在給出簡(jiǎn)單的用法

          mytext?=?r"今天是個(gè)好日子,是一個(gè)適合學(xué)習(xí)的好日子"
          fenci?=?jieba.cut(mytext)
          print(type(fenci))
          for?i?in?fenci:
          ????print(i)
          >>>
          'generator'>
          今天

          個(gè)
          好日子


          一個(gè)
          適合
          學(xué)習(xí)

          好日子

          可以看到,cut 函數(shù)返回的是一個(gè)生成器,我們通過(guò) for 循環(huán)逐個(gè)取出生成器中的內(nèi)容,已經(jīng)是一個(gè)個(gè)被切分的單詞了。

          還記得我們前面講解文本到向量里提到的,把文本分割成單詞,就可以(也是最常用)使用這里的 jieba 分詞庫(kù)工具。

          文本向量化

          接下來(lái)我們就需要把已經(jīng)處理過(guò)的文本進(jìn)行向量化

          首先使用 count vector,在 sklearn 中直接導(dǎo)入使用即可

          from?sklearn.feature_extraction.text?import?CountVectorizer

          然后就可以使用 CountVectorizer 來(lái)擬合數(shù)據(jù),生成一個(gè)稀疏矩陣

          稀疏矩陣是指大部分元素都是0的矩陣

          count_vector?=?CountVectorizer()
          X_train?=?count_vector.fit_transform(train_comments_new)
          y_train?=?train_labels
          print(X_train)
          >>>
          ??(0,?22983)????1
          ??(0,?4011)????1
          ??(0,?10618)????1
          ??(0,?1)????1
          ??(0,?18550)????1

          最終我們得到的 X_train 就是一個(gè)稀疏矩陣,前面括號(hào)里的數(shù)字表示矩陣位置,后面的數(shù)字代表詞頻

          對(duì)測(cè)試數(shù)據(jù)同樣進(jìn)行轉(zhuǎn)換

          X_test?=?count_vector.transform(test_comments_new)
          y_test?=?test_labels

          查看訓(xùn)練數(shù)據(jù)和測(cè)試數(shù)據(jù)的大小

          print(np.shape(X_train),?np.shape(X_test),?np.shape(y_train),?np.shape(y_test))
          >>>
          (8064,?23101)?(2500,?23101)?(8064,)?(2500,)

          總共有8064個(gè)樣本,每個(gè)樣本的維度是23101維,即詞庫(kù)中單詞的個(gè)數(shù)是23101個(gè)

          訓(xùn)練樸素貝葉斯分類(lèi)器

          在 sklearn 中,提供了三種樸素貝葉斯模型, ? ?分別是 GaussianNB,MultinomialNB 和BernoulliNB。

          GaussianNB 是先驗(yàn)概率屬于高斯分布的樸素貝葉斯,適用于特征變量為連續(xù)變量,比如人的身高,物體的長(zhǎng)度等。

          MultinomialNB 是先驗(yàn)概率為多項(xiàng)式分布的樸素貝葉斯,也就是上一節(jié)我們推導(dǎo)的樸素貝葉斯,適用于特征變量是離散型變量,比如詞袋模型中體現(xiàn)的詞頻。

          BernoulliNB 是先驗(yàn)概率為伯努利分布的樸素貝葉斯,即符合0/1分布的變量,比如文檔分類(lèi)中檢查單詞是否出現(xiàn)。

          本課程只介紹 MultinomialNB 算法,其他兩個(gè)可以作為課后的拓展內(nèi)容學(xué)習(xí)。MultinomialNB 的一些重要參數(shù)如下:

          alpha:為平滑參數(shù)。還記得我們的貝葉斯公式吧,如果每個(gè)特征在訓(xùn)練樣本中時(shí)沒(méi)有出現(xiàn)的,那么這個(gè)特征的概率就是0,從而整體的概率也就是0了,這是不合理的,所以引入平滑參數(shù)來(lái)規(guī)避概率為0的情況。

          fit_prior:默認(rèn)為 True,表示十分要考慮先驗(yàn)概率,如果是 False,則所有的樣本類(lèi)別輸出都有相同的類(lèi)別先驗(yàn)概率。否則可以讓 MultinomialNB 自己從訓(xùn)練集樣本來(lái)計(jì)算先驗(yàn)概率。

          這里我們使用 MultinomialNB 算法模型進(jìn)行訓(xùn)練

          from?sklearn.naive_bayes?import?MultinomialNB
          from?sklearn.metrics?import?accuracy_score
          clf?=?MultinomialNB(alpha=1.0,?fit_prior=True)
          #?利用樸素貝葉斯做訓(xùn)練
          clf.fit(X_train,?y_train)
          y_pred?=?clf.predict(X_test)
          print("accuracy?on?test?data:?",?accuracy_score(y_test,?y_pred))
          >>>
          accuracy?on?test?data:??0.7276

          文檔分類(lèi)

          數(shù)據(jù)集共分為4類(lèi),如下:

          下面就通過(guò)訓(xùn)練一個(gè)樸素貝葉斯分類(lèi)器,來(lái)判別測(cè)試集中的文檔類(lèi)別。

          首先還是處理文本,把文檔和對(duì)應(yīng)的分類(lèi)讀入內(nèi)存

          首先寫(xiě)一個(gè)切割文檔的函數(shù)

          def?cut_word(file):
          ????text?=?open(file,?'r',?encoding='gb18030').read()
          ????stopword?=?[line.strip()?for?line?in?open(r'text/stop/stopword.txt',?encoding='utf-8').readlines()]
          ????text_segd?=?jieba.cut(text.strip())
          ????seg_word?=?''
          ????for?word?in?text_segd:
          ????????if?word?not?in?stopword:
          ????????????seg_word?+=?word?+?'?'
          ????return?seg_word

          依然使用 jieba 做分詞,同時(shí)處理停用詞,返回一個(gè)大的字符串

          下面再編寫(xiě)導(dǎo)入文件的函數(shù),在函數(shù)中調(diào)用 cut_word 函數(shù)做分詞

          def?load_file(file_path,?label):
          ????file_list?=?os.listdir(file_path)
          ????words_list,?labels_list?=?[],?[]
          ????for?f?in?file_list:
          ????????file?=?file_path?+?'/'?+?f
          ????????words_list.append(cut_word(file))
          ????????labels_list.append(label)
          ????return?words_list,?labels_list

          設(shè)想是,總共四個(gè)分類(lèi)文件,依次讀入并設(shè)置標(biāo)簽

          依次讀入文件

          #?訓(xùn)練數(shù)據(jù)
          train_words_list1,?train_labels1?=?load_file('text/train/女性',?'女性')
          train_words_list2,?train_labels2?=?load_file('text/train/體育',?'體育')
          train_words_list3,?train_labels3?=?load_file('text/train/文學(xué)',?'文學(xué)')
          train_words_list4,?train_labels4?=?load_file('text/train/校園',?'校園')train_words_list?=?train_words_list1?+?train_words_list2?+?train_words_list3?+?train_words_list4
          train_labels?=?train_labels1?+?train_labels2?+?train_labels3?+?train_labels4#?測(cè)試數(shù)據(jù)
          test_words_list1,?test_labels1?=?load_file('text/test/女性',?'女性')
          test_words_list2,?test_labels2?=?load_file('text/test/體育',?'體育')
          test_words_list3,?test_labels3?=?load_file('text/test/文學(xué)',?'文學(xué)')
          test_words_list4,?test_labels4?=?load_file('text/test/校園',?'校園')test_words_list?=?test_words_list1?+?test_words_list2?+?test_words_list3?+?test_words_list4
          test_labels?=?test_labels1?+?test_labels2?+?test_labels3?+?test_labels4

          這次我們使用 TF-IDF 的方式來(lái)做文本轉(zhuǎn)向量的操作

          tf?=?TfidfVectorizer()train_features?=?tf.fit_transform(train_words_list)
          test_features?=?tf.transform(test_words_list)

          模型預(yù)測(cè)

          clf?=?MultinomialNB(alpha=0.001)
          clf.fit(train_features,?train_labels)
          predicted_labels?=?clf.predict(test_features)#?計(jì)算準(zhǔn)確率
          print('準(zhǔn)確率為:', metrics.accuracy_score(test_labels, predicted_labels))
          >>>
          準(zhǔn)確率為:?0.91

          可以看到,準(zhǔn)確率還是相當(dāng)不錯(cuò)的

          混淆矩陣

          下面再來(lái)介紹一個(gè)概念,混淆矩陣。

          我們先來(lái)看下如何打印混淆矩陣

          from?sklearn.metrics?import?confusion_matrix
          #?混淆矩陣
          print(confusion_matrix(test_labels,?predicted_labels,?labels=['女性',?'體育',?'文學(xué)',?'校園']))
          >>>
          [[?36???1???1???0]
          ?[??3?106???5???1]
          ?[??0???1??30???0]
          ?[??1???3???2??10]]

          為了方便理解,我們可以把混淆矩陣改表格的形式


          女性
          體育
          文學(xué)
          校園
          女性36110
          體育310651
          文學(xué)01300
          校園13210

          對(duì)于“女性”這個(gè)測(cè)試分類(lèi),總共有38個(gè)測(cè)試數(shù)據(jù),其中36個(gè)分類(lèi)正確,有3個(gè)測(cè)試數(shù)據(jù)分類(lèi)錯(cuò)誤,分別錯(cuò)誤的分類(lèi)到了體育、文學(xué)和校園下。

          同理,對(duì)于“體育”測(cè)試分類(lèi),總共有115個(gè)測(cè)試數(shù)據(jù),其中106個(gè)是正確分類(lèi)的,有3個(gè)錯(cuò)誤的分類(lèi)到了女性當(dāng)中,有5個(gè)錯(cuò)誤的分類(lèi)到文學(xué)當(dāng)中,有1個(gè)錯(cuò)誤的分類(lèi)到校園當(dāng)中。

          另外兩個(gè)類(lèi)似。

          可以看出在對(duì)角線上的36,106,30,10是正確的分類(lèi),而其余位置則是各數(shù)據(jù)的錯(cuò)誤分類(lèi),可以清楚的通過(guò)混淆矩陣看出哪些分類(lèi)是容易混淆的,比如有5個(gè)體育類(lèi)文檔錯(cuò)誤的分類(lèi)到了文學(xué)當(dāng)中。

          這樣可以幫助我們更好的分析數(shù)據(jù)和分類(lèi)器的效果,對(duì)容易混淆的分類(lèi)做一些更加細(xì)致的處理。

          完整代碼

          https://github.com/zhouwei713/DataAnalyse/tree/master/Naive_Bayes

          總結(jié)

          本節(jié)我們列舉了兩個(gè)實(shí)戰(zhàn)例子,希望你能從實(shí)戰(zhàn)中更好的體會(huì)樸素貝葉斯的應(yīng)用方法。

          同時(shí)我們還知道,自然語(yǔ)言處理是樸素貝葉斯應(yīng)用的最為廣泛的領(lǐng)域,一般的流程為,先分析文本的類(lèi)型、內(nèi)容組成等信息,再對(duì)文本進(jìn)行處理,如果是中文文本可以使用 jieba 工具做分成并打標(biāo)簽,再次通過(guò)詞袋模型或者 TF-IDF 模型來(lái)處理分詞的權(quán)重,進(jìn)行文本向量化,得到特征矩陣,最后就可以構(gòu)建分類(lèi)器,進(jìn)行訓(xùn)練和預(yù)測(cè)了。


          瀏覽 62
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99热99这里只有精品6首页 | 操屄免费视频 | 成人做爱小视频 | 蜜桃97夜夜做亚洲欧美 | 午夜做受|