1. 程式人生 > >機器學習分類實例——SVM(修改)/Decision Tree/Naive Bayes

機器學習分類實例——SVM(修改)/Decision Tree/Naive Bayes

nature console 內容 sign dal 一次 .html not cat

機器學習分類實例——SVM(修改)/Decision Tree/Naive Bayes

20180427-28筆記、30總結

已經5月了,畢設告一段落了,該準備論文了。前天開會老師說,希望我以後做關於語義分析那一塊內容,會議期間還討論了學姐的知識圖譜的知識推理內容,感覺也挺有趣的,但是感覺應該會比較復雜。有時間的話希望對這塊了解一下。其實吧,具體怎麽展示我還是不太清楚。。。
技術分享圖片大概就是圖表那個樣子。我先做一個出來,讓老師看看,兩個禮拜寫論文。24/25答辯,6月就可以去浪哈哈哈哈哈哈。

一、工作

工作主要是三個部分——修改SVM部分的代碼(精簡)、繪制圖表、修改DT和NBY的代碼

1.修改SVM部分的代碼

由於需要將預測三個標簽的分數,一次打印出來。所以需要分別訓練三個模型並一次將預測文本輸入三個模型進行預測。

那麽就是:


    x = vec[:,:-3]
    y = vec[:,-3]
    y2=vec[:,-2]
    y3=vec[:,-1]
    
    f = open("examout.txt","r")
    newl =f.read()
    newl=list(map(str,newl.strip().split(‘,‘)))
    newv = np.array(newl)
    new_test_x = newv[:]
  
#    模型1
    train_x,test_x,train_y,test_y = train_test_split(x,y,test_size=0.2)
    clf1 = SVC(kernel=‘linear‘,C=0.4)
    clf1.fit(train_x,train_y)
    pred_y = clf1.predict(test_x)
    new_pred_y1 = clf1.predict(new_test_x.reshape(1,-1))
    npy1=int(new_pred_y1[0])

#   模型2
    train_x2,test_x2,train_y2,test_y2 = train_test_split(x,y2,test_size=0.2)
    clf2= SVC(kernel=‘linear‘,C=0.4)
    clf2.fit(train_x2,train_y2)
    pred_y2 = clf2.predict(test_x2)
    new_pred_y2 = clf2.predict(new_test_x.reshape(1,-1))
    npy2=int(new_pred_y2[0])
    
#   模型3
    train_x3,test_x3,train_y3,test_y3 = train_test_split(x,y3,test_size=0.2)
    clf3= SVC(kernel=‘linear‘,C=0.4)
    clf3.fit(train_x3,train_y3)
    pred_y3 = clf3.predict(test_x3)    
    new_pred_y3 = clf3.predict(new_test_x.reshape(1,-1))
    npy3=int(new_pred_y3[0])

這樣就得到了3個模型。

在上次代碼中,我們通過函數classification_report(test_y,pred_y)可以得到模型的精確率、召回率及F1值。

             (precision    recall  f1-score)   support

          1       0.88      0.93      0.90       187
          2       0.00      0.00      0.00        11
          3       0.15      0.18      0.17        11
          4       0.00      0.00      0.00         7
          5       0.00      0.00      0.00         2

avg / total       0.76      0.81      0.78       218

在這裏,三個模型分別對應不同的(precision、recall、f1-score),我們希望獲取上表最後一排的值,最後繪制成一張表,就像這樣:

技術分享圖片

那麽問題來了,如何獲得classification_report()中的值呢。有兩種辦法:

  • (1)將內容輸出到文本,然後再從文本讀取
  • (2)讀取print輸出流

兩種辦法我都試過了,第一種方法比較熟悉,所以一下就寫完了:

    ff = open("crout.txt","w")
    ff.write(classification_report(test_y,pred_y))
    ff.close()
    ff2=open("crout.txt","r")
    cr=[]
    for line in ff2.readlines():
        cr.append(list(map(str,line.strip().split(‘,‘))))
    ss =str(cr[8]) #把最後一列整列打印出來[‘avg / total       0.89      0.92      0.90       218‘]
    
    #運用正則表達式找出小數
    fs1=[]
    for i in range(3):
        s = re.findall("\d+(\.\d+)?",ss)[i]
        s=‘0‘+s
        s=float(s)
        fs1.append(s)
    print (fs1)

很明顯,上面3個模型,就需要3個文本,寫來寫去的,感覺又麻煩又low...所以這種方式看看就好。這時候我們用print輸出流,來解決獲取數值的問題。我通過百度,在百度知道中看到了答案——如何獲取python print語句打印到console的值

把原來的代碼精簡一些,用函數表示,別寫在程序主體位置

class TextArea(object):  
    def __init__(self):  
        self.buffer = []  
    def write(self, *args, **kwargs): 
        self.buffer.append(args)  
        
def mf(L=[]):
    for i in range(90):
        s = re.findall("\d+(\.\d+)?",l)[i]
        s=‘0‘+s
        s=float(s)
        #通過觀察,在正則表達式獲取的小數中,所需要三個模型的P/R/F值分別位於26~28、56~58、86~88位置上,將其加入L中即可
        if i>=26 and i<=28 or i>=56 and i<=58 or i>=86 and i<=88:
            L.append(s) 
    return L

再寫函數主體:

    stdout = sys.stdout  
    sys.stdout = TextArea()  
    print(classification_report(test_y,pred_y))
    print(classification_report(test_y2,pred_y2))
    print(classification_report(test_y3,pred_y3))
    
    text_area, sys.stdout = sys.stdout, stdout  
      
    l=str(text_area.buffer)
    L=[]
    L=mf(L)
    #結果L=[0.76, 0.81, 0.78, 0.91, 0.94, 0.92, 0.73, 0.75, 0.74]
    fs1=[]
    fs2=[]
    fs3=[]
    LL=range(9)
    for i in LL[:9:3]:
        fs1.append(L[i])
        fs2.append(L[i+1])
        fs3.append(L[i+2])

2.繪制圖表

在這裏我們得到了每個模型的precision、recall、f1-score值(分別存在fs1,fs2,fs3中),以及預測文本的預測結果npy1、npy2、npy3三個分數。

(1)預測圖表

x = np.arange(3)
data = [npy1, npy2, npy3]

labels = [‘民主制度‘, ‘民主自由‘, ‘民主監督‘]
plt.ylim(ymax=5.5, ymin=0)
plt.ylabel("評分")
plt.title("預測")
plt.bar(x, data,alpha=0.9,tick_label=labels)
plt.show()

結果:

技術分享圖片

這樣直觀多了,上回是只給了一個“5”的評分,這樣三個都能得到了。

(2)precision、recall、f1-score值模型對比

total_width, n = 0.6, 3
x = np.arange(n)
width = total_width / n
x = x - (total_width - width) / 2
plt.ylim(ymax=1.3, ymin=0)
plt.bar(x, fs1,alpha=0.8, width=width, label=‘Precision‘)
plt.bar(x + width, fs2,alpha=0.8, width=width, label=‘Recall‘,tick_label = labels)
plt.bar(x + 2 * width, fs3, alpha=0.8,width=width, label=‘F1-score‘)
plt.legend()
plt.show()

得到如下結果:

技術分享圖片

3.修改DT和NBY的代碼

(1) Decision Tree

決策樹的代碼和SVM完全一樣的,就是函數名字不一樣。在這裏直接看結果就好了:
技術分享圖片
技術分享圖片

嗯...準確率挺高不錯。

(2) Naive Bayes

樸素貝葉斯在代碼上,和SVM也是一樣的,但是在預測的時候,有個地方報錯了

 new_pred_y1 = clf.predict(new_test_x.reshape(1,-1))

報錯:

TypeError: ufunc ‘subtract‘ did not contain a loop with signature matching types dtype(‘<U32‘) dtype(‘<U32‘) dtype(‘<U32‘)

怎麽回事呢,原來是需要將new_test_x轉為float64.
參考python TypeError: ufunc ‘subtract‘ did not contain a loop with signature matching typesdtype(‘S32‘)
只要在原來的代碼加上一句轉換就可以了:

    new_test_x = new_test_x.astype(‘float64‘)
    new_pred_y1 = clf.predict(new_test_x.reshape(1,-1))

那麽我們來看看結果:

技術分享圖片
技術分享圖片

貝葉斯效果就比較差了。。。民主制度的準確率最低,預測效果最不好。但是給的文本,對民主制度的評分還是最高,預測效果還行。

二、總結反思

  • 改進了代碼,原來寫的有點亂七八糟。
  • 學習了圖表的繪制,遇到了matplotlib的圖表不能顯示中文的問題。就是圖表中的中文都變成了框框,怎麽解決呢?參考Python中,matplotlib繪圖無法顯示中文的問題

三、接下來的任務

  • 人工選取一些測試集,測試在評分誤差為±1的情況下,準確率是多少。之前測了一些,是在訓練集中選取的一些帖子,準確率達到了95%,雖然很高但是不準。
  • 學習論文撰寫。

機器學習分類實例——SVM(修改)/Decision Tree/Naive Bayes