<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                作者:?[寒小陽](http://blog.csdn.net/han_xiaoyang?viewmode=contents)?&&?[龍心塵](http://blog.csdn.net/longxinchen_ml?viewmode=contents)? 時間:2016年2月。? 出處:[http://blog.csdn.net/han_xiaoyang/article/details/50629608](http://blog.csdn.net/han_xiaoyang/article/details/50629608)? [http://blog.csdn.net/longxinchen_ml/article/details/50629613](http://blog.csdn.net/longxinchen_ml/article/details/50629613)? 聲明:版權所有,轉載請聯系作者并注明出處 ### 1.引言 前兩篇博文介紹了樸素貝葉斯這個名字讀著”萌蠢”但實際上簡單直接高效的方法,我們也介紹了一下貝葉斯方法的一些細節。按照老規矩,『鋤頭』給你了,得負責教教怎么用和注意事項,也順便帶大家去除除草對吧。恩,此節作為更貼近實際應用的部分,將介紹貝葉斯方法的優缺點、常見適用場景和可優化點,然后找點實際場景擼點例子練練手,看看工具怎么用。 **PS:本文所有的python代碼和ipython notebook已整理至[github相應頁面](https://github.com/HanXiaoyang/naive_bayes),歡迎下載和嘗試。** ### 2.貝葉斯方法優缺點 既然講的是樸素貝葉斯,那博主保持和它一致的風格,簡單直接高效地丟干貨了: * 優點 > 1. 對待預測樣本進行預測,**過程簡單速度快**(想想郵件分類的問題,預測就是分詞后進行概率乘積,在log域直接做加法更快)。 > 2. **對于多分類問題也同樣很有效**,復雜度也不會有大程度上升。 > 3. **在分布獨立這個假設成立的情況下**,貝葉斯分類器**效果奇好**,會略勝于邏輯回歸,同時我們**需要的樣本量也更少一點**。 > 4. 對于類別類的輸入特征變量,效果非常好。對于數值型變量特征,我們是默認它符合正態分布的。 * 缺點 > 1. 對于測試集中的一個類別變量特征,如果在訓練集里沒見過,直接算的話概率就是0了,預測功能就失效了。當然,我們前面的文章提過我們有一種技術叫做**『平滑』操作**,可以緩解這個問題,最常見的平滑技術是拉普拉斯估測。 > 2. 那個…咳咳,樸素貝葉斯算出的概率結果,比較大小還湊合,實際物理含義…恩,別太當真。 > 3. 樸素貝葉斯有分布獨立的假設前提,而**現實生活中這些predictor很難是完全獨立的**。 ### 3.最常見應用場景 * 文本分類/垃圾文本過濾/情感判別:這大概會樸素貝葉斯應用做多的地方了,即使在現在這種分類器層出不窮的年代,在文本分類場景中,樸素貝葉斯依舊堅挺地占據著一席之地。原因嘛,大家知道的,因為多分類很簡單,同時在文本數據中,分布獨立這個假設基本是成立的。而垃圾文本過濾(比如垃圾郵件識別)和情感分析(微博上的褒貶情緒)用樸素貝葉斯也通常能取得很好的效果。 * 多分類實時預測:這個是不是不能叫做場景?對于文本相關的多分類實時預測,它因為上面提到的優點,被廣泛應用,簡單又高效。 * 推薦系統:是的,你沒聽錯,是用在推薦系統里!!樸素貝葉斯和協同過濾([Collaborative Filtering](https://en.wikipedia.org/wiki/Collaborative_filtering))是一對好搭檔,協同過濾是強相關性,但是泛化能力略弱,樸素貝葉斯和協同過濾一起,能增強推薦的覆蓋度和效果。 ### 4.樸素貝葉斯注意點 這個部分的內容,本來應該在最后說的,不過為了把干貨集中放在代碼示例之前,先擱這兒了,大家也可以看完樸素貝葉斯的各種例子之后,回來再看看這些tips。 * 大家也知道,很多特征是連續數值型的,但是它們不一定服從正態分布,一定要想辦法把它們變換調整成滿足正態分布!! * 對測試數據中的0頻次項,一定要記得平滑,簡單一點可以用『拉普拉斯平滑』。 * 先處理處理特征,把相關特征去掉,因為高相關度的2個特征在模型中相當于發揮了2次作用。 * 樸素貝葉斯分類器一般可調參數比較少,比如[scikit-learn中的樸素貝葉斯](http://scikit-learn.org/stable/modules/generated/sklearn.naive_bayes.MultinomialNB.html#sklearn.naive_bayes.MultinomialNB)只有拉普拉斯平滑因子alpha,類別先驗概率class_prior和預算數據類別先驗fit_prior。模型端可做的事情不如其他模型多,因此我們還是集中精力進行數據的預處理,以及特征的選擇吧。 * 那個,一般其他的模型(像logistic regression,SVM等)做完之后,我們都可以嘗試一下bagging和boosting等融合增強方法。咳咳,很可惜,對樸素貝葉斯里這些方法都沒啥用。原因?原因是這些融合方法本質上是減少過擬合,減少variance的。樸素貝葉斯是沒有variance可以減小。 ### 5\. 樸素貝葉斯訓練/建模 理論干貨和注意點都說完了,來提提怎么快速用樸素貝葉斯訓練模型吧。博主一直提倡要站在巨人的肩膀上編程(其實就是懶…同時一直很擔憂寫出來的代碼的健壯性…),咳咳,我們又很自然地把scikit-learn拿過來了。scikit-learn里面有3種不同類型的樸素貝葉斯: * **[高斯分布型](http://scikit-learn.org/stable/modules/naive_bayes.html#gaussian-naive-bayes)**:用于classification問題,假定屬性/特征是服從正態分布的。 * **[多項式型](http://scikit-learn.org/stable/modules/naive_bayes.html#multinomial-naive-bayes)**:用于離散值模型里。比如文本分類問題里面我們提到過,我們不光看詞語是否在文本中出現,也得看出現的次數。如果總詞數為n,出現詞數為m的話,說起來有點像擲骰子n次出現m次這個詞的場景。 * **[伯努利型](http://scikit-learn.org/stable/modules/naive_bayes.html#bernoulli-naive-bayes)**:這種情況下,就如之前博文里提到的bag of words處理方式一樣,最后得到的特征只有0(沒出現)和1(出現過)。 根據你的數據集,可以選擇scikit-learn中以上任意一種樸素貝葉斯,我們直接舉個簡單的例子,用高斯分布型樸素貝葉斯建模: ~~~ # 我們直接取iris數據集,這個數據集有名到都不想介紹了... # 其實就是根據花的各種數據特征,判定是什么花 from sklearn import datasets iris = datasets.load_iris() iris.data[:5] #array([[ 5.1, 3.5, 1.4, 0.2], # [ 4.9, 3\. , 1.4, 0.2], # [ 4.7, 3.2, 1.3, 0.2], # [ 4.6, 3.1, 1.5, 0.2], # [ 5\. , 3.6, 1.4, 0.2]]) #我們假定sepal length, sepal width, petal length, petal width 4個量獨立且服從高斯分布,用貝葉斯分類器建模 from sklearn.naive_bayes import GaussianNB gnb = GaussianNB() y_pred = gnb.fit(iris.data, iris.target).predict(iris.data) right_num = (iris.target == y_pred).sum() print("Total testing num :%d , naive bayes accuracy :%f" %(iris.data.shape[0], float(right_num)/iris.data.shape[0])) # Total testing num :150 , naive bayes accuracy :0.960000 ~~~ 你看,樸素貝葉斯分類器,簡單直接高效,在150個測試樣本上,準確率為96%。 ### 6.樸素貝葉斯之文本主題分類器 這是樸素貝葉斯最擅長的應用場景之一,對于不同主題的文本,我們可以用樸素貝葉斯訓練一個分類器,然后將其應用在新數據上,預測主題類型。 **6.1 新聞數據分類** 我們使用[搜狐新聞數據](http://www.sogou.com/labs/dl/cs.html)來實驗樸素貝葉斯分類器,這部分新聞數據包括it、汽車、財經、健康等9個類別,簡潔版數據解壓縮后總共16289條新聞,一篇新聞一個txt,我們把數據合并到一個大文件中,一行一篇文章,同時將新聞id(指明新聞的類別)放在文章之前,然后用ICTCLAS(python的話你也可以用[結巴分詞](https://github.com/fxsjy/jieba))進行分詞,得到以下的文本內容:? ![](https://box.kancloud.cn/2016-03-11_56e2431113eed.jpg)? 我們隨機選取3/5的數據作為訓練集,2/5的數據作為測試集,采用互信息對文本特征進行提取,提取出1000個左右的特征詞。然后用樸素貝葉斯分類器進行訓練,實際訓練過程就是對于特征詞,統計在訓練集和各個類別出現的次數,測試階段做預測也是掃描一遍測試集,計算相應的概率。因此整個過程非常高效,完整的運行代碼如下: ~~~ # 這部分代碼基本純手擼的...沒有調用開源庫...大家看看就好... #!encoding=utf-8 import sys, math, random, collections def shuffle(inFile): ''' 簡單的亂序操作,用于生成訓練集和測試集 ''' textLines = [line.strip() for line in open(inFile)] print "正在準備訓練和測試數據,請稍后..." random.shuffle(textLines) num = len(textLines) trainText = textLines[:3*num/5] testText = textLines[3*num/5:] print "準備訓練和測試數據準備完畢,下一步..." return trainText, testText #總共有9種新聞類別,我們給每個類別一個編號 lables = ['A','B','C','D','E','F','G','H','I'] def lable2id(lable): for i in xrange(len(lables)): if lable == lables[i]: return i raise Exception('Error lable %s' % (lable)) def doc_dict(): ''' 構造和類別數等長的0向量 ''' return [0]*len(lables) def mutual_info(N,Nij,Ni_,N_j): ''' 計算互信息,這里log的底取為2 ''' return Nij * 1.0 / N * math.log(N * (Nij+1)*1.0/(Ni_*N_j))/ math.log(2) def count_for_cates(trainText, featureFile): ''' 遍歷文件,統計每個詞在每個類別出現的次數,和每類的文檔數 并寫入結果特征文件 ''' docCount = [0] * len(lables) wordCount = collections.defaultdict(doc_dict()) #掃描文件和計數 for line in trainText: lable,text = line.strip().split(' ',1) index = lable2id(lable[0]) words = text.split(' ') for word in words: wordCount[word][index] += 1 docCount[index] += 1 #計算互信息值 print "計算互信息,提取關鍵/特征詞中,請稍后..." miDict = collections.defaultdict(doc_dict()) N = sum(docCount) for k,vs in wordCount.items(): for i in xrange(len(vs)): N11 = vs[i] N10 = sum(vs) - N11 N01 = docCount[i] - N11 N00 = N - N11 - N10 - N01 mi = mutual_info(N,N11,N10+N11,N01+N11) + mutual_info(N,N10,N10+N11,N00+N10)+ mutual_info(N,N01,N01+N11,N01+N00)+ mutual_info(N,N00,N00+N10,N00+N01) miDict[k][i] = mi fWords = set() for i in xrange(len(docCount)): keyf = lambda x:x[1][i] sortedDict = sorted(miDict.items(),key=keyf,reverse=True) for j in xrange(100): fWords.add(sortedDict[j][0]) out = open(featureFile, 'w') #輸出各個類的文檔數目 out.write(str(docCount)+"\n") #輸出互信息最高的詞作為特征詞 for fword in fWords: out.write(fword+"\n") print "特征詞寫入完畢..." out.close() def load_feature_words(featureFile): ''' 從特征文件導入特征詞 ''' f = open(featureFile) #各個類的文檔數目 docCounts = eval(f.readline()) features = set() #讀取特征詞 for line in f: features.add(line.strip()) f.close() return docCounts,features def train_bayes(featureFile, textFile, modelFile): ''' 訓練貝葉斯模型,實際上計算每個類中特征詞的出現次數 ''' print "使用樸素貝葉斯訓練中..." docCounts,features = load_feature_words(featureFile) wordCount = collections.defaultdict(doc_dict()) #每類文檔特征詞出現的次數 tCount = [0]*len(docCounts) for line in open(textFile): lable,text = line.strip().split(' ',1) index = lable2id(lable[0]) words = text.split(' ') for word in words: if word in features: tCount[index] += 1 wordCount[word][index] += 1 outModel = open(modelFile, 'w') #拉普拉斯平滑 print "訓練完畢,寫入模型..." for k,v in wordCount.items(): scores = [(v[i]+1) * 1.0 / (tCount[i]+len(wordCount)) for i in xrange(len(v))] outModel.write(k+"\t"+scores+"\n") outModel.close() def load_model(modelFile): ''' 從模型文件中導入計算好的貝葉斯模型 ''' print "加載模型中..." f = open(modelFile) scores = {} for line in f: word,counts = line.strip().rsplit('\t',1) scores[word] = eval(counts) f.close() return scores def predict(featureFile, modelFile, testText): ''' 預測文檔的類標,標準輸入每一行為一個文檔 ''' docCounts,features = load_feature_words() docScores = [math.log(count * 1.0 /sum(docCounts)) for count in docCounts] scores = load_model(modelFile) rCount = 0 docCount = 0 print "正在使用測試數據驗證模型效果..." for line in testText: lable,text = line.strip().split(' ',1) index = lable2id(lable[0]) words = text.split(' ') preValues = list(docScores) for word in words: if word in features: for i in xrange(len(preValues)): preValues[i]+=math.log(scores[word][i]) m = max(preValues) pIndex = preValues.index(m) if pIndex == index: rCount += 1 #print lable,lables[pIndex],text docCount += 1 print("總共測試文本量: %d , 預測正確的類別量: %d, 樸素貝葉斯分類器準確度:%f" %(rCount,docCount,rCount * 1.0 / docCount)) if __name__=="__main__": if len(sys.argv) != 4: print "Usage: python naive_bayes_text_classifier.py sougou_news.txt feature_file.out model_file.out" sys.exit() inFile = sys.argv[1] featureFile = sys.argv[2] modelFile = sys.argv[3] trainText, testText = shuffle(inFile) count_for_cates(trainText, featureFile) train_bayes(featureFile, trainText, modelFile) predict(featureFile, modelFile, testText) ~~~ **6.2 分類結果** 運行結果如下,在6515條數據上,9個類別的新聞上,有84.1%的準確度:? ![](https://box.kancloud.cn/2016-03-11_56e2431127da6.jpg)? ### 7\. Kaggle比賽之『舊金山犯罪分類預測』 **7.1 舊金山犯罪分類預測問題** 沒過癮對吧,確實每次學完一個機器學習算法,不在實際數據上倒騰倒騰,總感覺不那么踏實(想起來高中各種理科科目都要找點題來做的感覺)。好,我們繼續去Kaggle扒點場景和數據來練練手。正巧之前[Kaggle](https://www.kaggle.com/)上有一個分類問題,場景和數據也都比較簡單,我們拿來用樸素貝葉斯試試水。問題請戳[這里](https://www.kaggle.com/c/sf-crime)。 **7.2 背景介紹** 我們大致介紹一下,說的是『水深火熱』的大米國,在舊金山這個地方,一度犯罪率還挺高的,然后很多人都經歷過大到暴力案件,小到東西被偷,車被劃的事情。當地警方也是努力地去總結和想辦法降低犯罪率,一個挑戰是在給出犯罪的地點和時間的之后,要第一時間確定這可能是一個什么樣的犯罪類型,以確定警力等等。后來干脆一不做二不休,直接把12年內舊金山城內的犯罪報告都丟帶Kaggle上,說『大家折騰折騰吧,看看誰能幫忙第一時間預測一下犯罪類型』。犯罪報告里面包括`日期`,`描述`,`星期幾`,`所屬警區`,`處理結果`,`地址`,`GPS定位`等信息。當然,分類問題有很多分類器可以選擇,我們既然剛講過樸素貝葉斯,剛好就拿來練練手好了。 **7.3 數據一瞥** 數據可以在[Kaggle比賽數據頁面](https://www.kaggle.com/c/sf-crime/data)下載到,大家也可以在博主提供的[百度網盤地址](http://pan.baidu.com/s/1o6Wgch8)中下載到。我們依舊用pandas載入數據,先看看數據內容。 ~~~ import pandas as pd import numpy as np #用pandas載入csv訓練數據,并解析第一列為日期格式 train=pd.read_csv('/Users/Hanxiaoyang/sf_crime_data/train.csv', parse_dates = ['Dates']) test=pd.read_csv('/Users/Hanxiaoyang/sf_crime_data/test.csv', parse_dates = ['Dates']) train ~~~ 得到如下的結果:? ![](https://box.kancloud.cn/2016-03-11_56e243114913e.png) 我們依次解釋一下每一列的含義: * Date: 日期 * Category: 犯罪類型,比如 Larceny/盜竊罪 等. * Descript: 對于犯罪更詳細的描述 * DayOfWeek: 星期幾 * PdDistrict: 所屬警區 * Resolution: 處理結果,比如說『逮捕』『逃了』 * Address: 發生街區位置 * X and Y: GPS坐標 train.csv中的數據時間跨度為12年,包含了90w+的記錄。另外,這部分數據,大家從上圖上也可以看出來,大部分都是『類別』型,比如犯罪類型,比如星期幾。 ### 7.4 特征預處理 上述數據中類別和文本型非常多,我們要進行特征預處理,對于特征預處理的部分,我們在前面的博文[機器學習系列(3)*邏輯回歸應用之Kaggle泰坦尼克之災*](http://blog.csdn.net/han_xiaoyang/article/details/49797143)和[機器學習系列(6)從白富美相親看特征預處理與選擇(下)](http://blog.csdn.net/han_xiaoyang/article/details/50503115)都有較細的介紹。對于類別特征,我們用最常見的因子化操作將其轉成數值型,比如我們把犯罪類型用因子化進行encode,也就是說生成如下的向量: ~~~ 星期一/Monday = 1,0,0,0,... 星期二/Tuesday = 0,1,0,0,... 星期三/Wednesday = 0,0,1,0,... ... ~~~ 我們之前也提到過,用pandas的[get_dummies()](http://pandas.pydata.org/pandas-docs/version/0.13.1/generated/pandas.get_dummies.html)可以直接拿到這樣的一個二值化的01向量。Pandas里面還有一個很有用的方法[LabelEncoder](http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.LabelEncoder.html)可以用于對類別編號。對于已有的數據特征,我們打算做下面的粗略變換: * 用LabelEncoder對犯罪類型做編號; * 處理時間,在我看來,也許犯罪發生的時間點(小時)是非常重要的,因此我們會用Pandas把這部分數據抽出來; * 對`街區`,`星期幾`,`時間點`用get_dummies()因子化; * 做一些組合特征,比如把上述三個feature拼在一起,再因子化一下; 具體的數據和特征處理如下: ~~~ import pandas as pd import numpy as np from sklearn.cross_validation import train_test_split from sklearn import preprocessing #用LabelEncoder對不同的犯罪類型編號 leCrime = preprocessing.LabelEncoder() crime = leCrime.fit_transform(train.Category) #因子化星期幾,街區,小時等特征 days = pd.get_dummies(train.DayOfWeek) district = pd.get_dummies(train.PdDistrict) hour = train.Dates.dt.hour hour = pd.get_dummies(hour) #組合特征 trainData = pd.concat([hour, days, district], axis=1) trainData['crime']=crime #對于測試數據做同樣的處理 days = pd.get_dummies(test.DayOfWeek) district = pd.get_dummies(test.PdDistrict) hour = test.Dates.dt.hour hour = pd.get_dummies(hour) testData = pd.concat([hour, days, district], axis=1) trainData ~~~ 然后可以看到特征處理后的數據如下所示:? ![](https://box.kancloud.cn/2016-03-11_56e243117fa62.png) ### 7.5 樸素貝葉斯 VS 邏輯回歸 拿到初步的特征了,下一步就可以開始建模了。 因為之前的博客[機器學習系列(1)*邏輯回歸初步*](http://blog.csdn.net/han_xiaoyang/article/details/49123419),[機器學習系列(2)從初等數學視角解讀邏輯回歸](http://blog.csdn.net/han_xiaoyang/article/details/49332321),[機器學習系列(3)_邏輯回歸應用之Kaggle泰坦尼克之災](http://blog.csdn.net/han_xiaoyang/article/details/49797143)中提到過邏輯回歸這種分類算法,我們這里打算一并拿來建模,做個比較。? 還需要提到的一點是,大家參加Kaggle的比賽,一定要注意最后排名和評定好壞用的標準,比如說在現在這個多分類問題中,Kaggle的評定標準并不是precision,而是[multi-class log_loss](http://scikit-learn.org/stable/modules/generated/sklearn.metrics.log_loss.html),這個值越小,表示最后的效果越好。 我們可以快速地篩出一部分重要的特征,搭建一個baseline系統,再考慮步步優化。比如我們這里簡單一點,就只取`星期幾`和`街區`作為分類器輸入特征,我們用scikit-learn中的`train_test_split`函數拿到訓練集和交叉驗證集,用樸素貝葉斯和邏輯回歸都建立模型,對比一下它們的表現: ~~~ ffrom sklearn.cross_validation import train_test_split from sklearn import preprocessing from sklearn.metrics import log_loss from sklearn.naive_bayes import BernoulliNB from sklearn.linear_model import LogisticRegression import time # 只取星期幾和街區作為分類器輸入特征 features = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'BAYVIEW', 'CENTRAL', 'INGLESIDE', 'MISSION', 'NORTHERN', 'PARK', 'RICHMOND', 'SOUTHERN', 'TARAVAL', 'TENDERLOIN'] # 分割訓練集(3/5)和測試集(2/5) training, validation = train_test_split(trainData, train_size=.60) # 樸素貝葉斯建模,計算log_loss model = BernoulliNB() nbStart = time.time() model.fit(training[features], training['crime']) nbCostTime = time.time() - nbStart predicted = np.array(model.predict_proba(validation[features])) print "樸素貝葉斯建模耗時 %f 秒" %(nbCostTime) print "樸素貝葉斯log損失為 %f" %(log_loss(validation['crime'], predicted)) #邏輯回歸建模,計算log_loss model = LogisticRegression(C=.01) lrStart= time.time() model.fit(training[features], training['crime']) lrCostTime = time.time() - lrStart predicted = np.array(model.predict_proba(validation[features])) log_loss(validation['crime'], predicted) print "邏輯回歸建模耗時 %f 秒" %(lrCostTime) print "邏輯回歸log損失為 %f" %(log_loss(validation['crime'], predicted)) ~~~ 實驗的結果如下: ![](https://box.kancloud.cn/2016-03-11_56e24311ac0df.jpg)? 我們可以看到目前的特征和參數設定下,樸素貝葉斯的log損失還低一些,另外我們可以明顯看到,樸素貝葉斯建模消耗的時間0.640398秒遠小于邏輯回歸建模42.856376秒。 考慮到犯罪類型可能和犯罪事件發生的小時時間點相關,我們加入小時時間點特征再次建模,代碼和結果如下: ~~~ from sklearn.cross_validation import train_test_split from sklearn import preprocessing from sklearn.metrics import log_loss from sklearn.naive_bayes import BernoulliNB from sklearn.linear_model import LogisticRegression import time # 添加犯罪的小時時間點作為特征 features = ['Friday', 'Monday', 'Saturday', 'Sunday', 'Thursday', 'Tuesday', 'Wednesday', 'BAYVIEW', 'CENTRAL', 'INGLESIDE', 'MISSION', 'NORTHERN', 'PARK', 'RICHMOND', 'SOUTHERN', 'TARAVAL', 'TENDERLOIN'] hourFea = [x for x in range(0,24)] features = features + hourFea # 分割訓練集(3/5)和測試集(2/5) training, validation = train_test_split(trainData, train_size=.60) # 樸素貝葉斯建模,計算log_loss model = BernoulliNB() nbStart = time.time() model.fit(training[features], training['crime']) nbCostTime = time.time() - nbStart predicted = np.array(model.predict_proba(validation[features])) print "樸素貝葉斯建模耗時 %f 秒" %(nbCostTime) print "樸素貝葉斯log損失為 %f" %(log_loss(validation['crime'], predicted)) #邏輯回歸建模,計算log_loss model = LogisticRegression(C=.01) lrStart= time.time() model.fit(training[features], training['crime']) lrCostTime = time.time() - lrStart predicted = np.array(model.predict_proba(validation[features])) log_loss(validation['crime'], predicted) print "邏輯回歸建模耗時 %f 秒" %(lrCostTime) print "邏輯回歸log損失為 %f" %(log_loss(validation['crime'], predicted)) ~~~ ![](https://box.kancloud.cn/2016-03-11_56e24311c9bfd.jpg)? 可以看到在這三個類別特征下,樸素貝葉斯相對于邏輯回歸,依舊有一定的優勢(log損失更小),同時訓練時間很短,這意味著模型雖然簡單,但是效果依舊強大。順便提一下,樸素貝葉斯1.13s訓練出來的模型,預測的效果在Kaggle排行榜上已經能進入Top 35%了,如果進行一些優化,比如特征處理、特征組合等,結果會進一步提高。 ### 8\. Kaggle比賽之影評與觀影者情感判定 博主想了想,既然樸素貝葉斯最常見的應用場景就那么幾個,干脆我們都一并覆蓋得了。咳咳,對,還有一個非常重要的應用場景是情感分析(尤其是褒貶判定),于是我又上Kaggle溜達了一圈,扒下來一個類似場景的比賽。比賽的名字叫做[**當詞袋/Bag of words 遇上 爆米花/Bags of Popcorn**](https://www.kaggle.com/c/word2vec-nlp-tutorial/),地址為[https://www.kaggle.com/c/word2vec-nlp-tutorial/](https://www.kaggle.com/c/word2vec-nlp-tutorial/),有興趣的同學可以上去瞄一眼。 **8.1 背景介紹** 這個比賽的背景大概是:國外有一個類似[豆瓣電影](http://movie.douban.com/)一樣的[IMDB](http://www.imdb.com/),也是你看完電影,可以上去打個分,吐個槽的地方。然后大家就在想,有這么多數據,總得折騰點什么吧,于是乎,第一個想到的就是,贊的噴的內容都有了,咱們就來分分類,看看能不能根據內容分布褒貶。PS:很多同學表示,分個褒貶有毛線難的,咳咳,計算機比較笨,另外,語言這種東西,真心是博大精深的,我們隨手從豆瓣上抓了幾條《功夫熊貓3》影評下來,表示有些雖然我是能看懂,但是不處理直接給計算機看,它應該是一副『什么鬼』的表情。。。 ![](https://box.kancloud.cn/2016-03-11_56e24311dfa0c.jpg)? 多說一句,Kaggle原文引導里是用word2vec的方式將詞轉為詞向量,后再用deep learning的方式做的。深度學習好歸好,但是畢竟耗時耗力耗資源,我們用最最naive的樸素貝葉斯擼一把,說不定效果也能不錯,不試試誰知道呢。另外,樸素貝葉斯建模真心速度快,很多場景下,快速建模快速迭代優化正是我們需要的嘛。 **8.2 數據一瞥** 言歸正傳,回到Kaggle中這個問題上來,先瞄一眼數據。Kaggle數據頁面地址為[https://www.kaggle.com/c/word2vec-nlp-tutorial/data](https://www.kaggle.com/c/word2vec-nlp-tutorial/data),大家也可以到博主的[百度網盤](http://pan.baidu.com/s/1c1jX8nI)中下載。數據包如下圖所示: ![](https://box.kancloud.cn/2016-03-11_56e2431209b18.jpg)? 其中包含有情緒標簽的訓練數據labeledTrainData,沒有情緒標簽的訓練數據unlabeledTrainData,以及測試數據testData。labeledTrainData包括id,sentiment和review3個部分,分別指代用戶id,情感標簽,評論內容。 解壓縮labeledTrainData后用vim打開,內容如下: ![](https://box.kancloud.cn/2016-03-11_56e243122425c.png) 下面我們讀取數據并做一些基本的預處理(比如說把評論部分的html標簽去掉等等): ~~~ import re #正則表達式 from bs4 import BeautifulSoup #html標簽處理 import pandas as pd def review_to_wordlist(review): ''' 把IMDB的評論轉成詞序列 ''' # 去掉HTML標簽,拿到內容 review_text = BeautifulSoup(review).get_text() # 用正則表達式取出符合規范的部分 review_text = re.sub("[^a-zA-Z]"," ", review_text) # 小寫化所有的詞,并轉成詞list words = review_text.lower().split() # 返回words return words # 使用pandas讀入訓練和測試csv文件 train = pd.read_csv('/Users/Hanxiaoyang/IMDB_sentiment_analysis_data/labeledTrainData.tsv', header=0, delimiter="\t", quoting=3) test = pd.read_csv('/Users/Hanxiaoyang/IMDB_sentiment_analysis_data/testData.tsv', header=0, delimiter="\t", quoting=3 ) # 取出情感標簽,positive/褒 或者 negative/貶 y_train = train['sentiment'] # 將訓練和測試數據都轉成詞list train_data = [] for i in xrange(0,len(train['review'])): train_data.append(" ".join(review_to_wordlist(train['review'][i]))) test_data = [] for i in xrange(0,len(test['review'])): test_data.append(" ".join(review_to_wordlist(test['review'][i]))) ~~~ 我們在ipython notebook里面看一眼,發現數據已經格式化了,如下:? ![](https://box.kancloud.cn/2016-03-11_56e243127e684.png) **8.3 特征處理** 緊接著又到了頭疼的部分了,數據有了,我們得想辦法從數據里面拿到有區分度的特征。比如說Kaggle該問題的引導頁提供的word2vec就是一種文本到數值域的特征抽取方式,比如說我們在第6小節提到的用互信息提取關鍵字也是提取特征的一種。比如說在這里,我們打算用在文本檢索系統中非常有效的一種特征:TF-IDF(term frequency-interdocument frequency)向量。每一個電影評論最后轉化成一個TF-IDF向量。對了,對于TF-IDF不熟悉的同學們,我們稍加解釋一下,TF-IDF是一種統計方法,用以評估一字詞(或者n-gram)對于一個文件集或一個語料庫中的其中一份文件的重要程度。字詞的重要性隨著它在文件中出現的次數成正比增加,但同時會隨著它在語料庫中出現的頻率成反比下降。這是一個能很有效地判定對評論褒貶影響大的詞或短語的方法。 那個…博主打算繼續偷懶,把scikit-learn中TFIDF向量化方法直接拿來用,想詳細了解的同學可以戳[sklearn TFIDF向量類](http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html)。對了,再多說幾句我的處理細節,停用詞被我掐掉了,同時我在單詞的級別上又拓展到2元語言模型(對這個不了解的同學別著急,后續的博客介紹馬上就來),恩,你可以再加3元4元語言模型…博主主要是單機內存不夠了,先就2元上,湊活用吧… ~~~ from sklearn.feature_extraction.text import TfidfVectorizer as TFIV # 初始化TFIV對象,去停用詞,加2元語言模型 tfv = TFIV(min_df=3, max_features=None, strip_accents='unicode', analyzer='word',token_pattern=r'\w{1,}', ngram_range=(1, 2), use_idf=1,smooth_idf=1,sublinear_tf=1, stop_words = 'english') # 合并訓練和測試集以便進行TFIDF向量化操作 X_all = train_data + test_data len_train = len(train_data) # 這一步有點慢,去喝杯茶刷會兒微博知乎歇會兒... tfv.fit(X_all) X_all = tfv.transform(X_all) # 恢復成訓練集和測試集部分 X = X_all[:len_train] X_test = X_all[len_train:] ~~~ **8.4 樸素貝葉斯 vs 邏輯回歸** 特征現在我們拿到手了,該建模了,好吧,博主折騰勁又上來了,那個…咳咳…我們還是樸素貝葉斯和邏輯回歸都建個分類器吧,然后也可以比較比較,恩。? 『talk is cheap, I’ll show you the code』,直接放碼過來了哈。 ~~~ # 多項式樸素貝葉斯 from sklearn.naive_bayes import MultinomialNB as MNB model_NB = MNB() model_NB.fit(X, y_train) #特征數據直接灌進來 MNB(alpha=1.0, class_prior=None, fit_prior=True) from sklearn.cross_validation import cross_val_score import numpy as np print "多項式貝葉斯分類器20折交叉驗證得分: ", np.mean(cross_val_score(model_NB, X, y_train, cv=20, scoring='roc_auc')) # 多項式貝葉斯分類器20折交叉驗證得分: 0.950837239 ~~~ ~~~ # 折騰一下邏輯回歸,恩 from sklearn.linear_model import LogisticRegression as LR from sklearn.grid_search import GridSearchCV # 設定grid search的參數 grid_values = {'C':[30]} # 設定打分為roc_auc model_LR = GridSearchCV(LR(penalty = 'L2', dual = True, random_state = 0), grid_values, scoring = 'roc_auc', cv = 20) # 數據灌進來 model_LR.fit(X,y_train) # 20折交叉驗證,開始漫長的等待... GridSearchCV(cv=20, estimator=LogisticRegression(C=1.0, class_weight=None, dual=True, fit_intercept=True, intercept_scaling=1, penalty='L2', random_state=0, tol=0.0001), fit_params={}, iid=True, loss_func=None, n_jobs=1, param_grid={'C': [30]}, pre_dispatch='2*n_jobs', refit=True, score_func=None, scoring='roc_auc', verbose=0) #輸出結果 print model_LR.grid_scores_ ~~~ 最后邏輯回歸的結果是`[mean: 0.96459, std: 0.00489, params: {'C': 30}]` 咳咳…看似邏輯回歸在這個問題中,TF-IDF特征下表現要稍強一些…不過同學們自己跑一下就知道,這2個模型的訓練時長真心不在一個數量級,邏輯回歸在數據量大的情況下,要等到睡著…另外,要提到的一點是,因為我這里只用了2元語言模型(2-gram),加到3-gram和4-gram,最后兩者的結果還會提高,而且樸素貝葉斯說不定會提升更快一點,內存夠的同學們自己動手試試吧^_^ ### 9\. 總結 本文為樸素貝葉斯的實踐和進階篇,先丟了點干貨,總結了貝葉斯方法的優缺點,應用場景,注意點和一般建模方法。緊接著對它最常見的應用場景,抓了幾個例子,又來了一遍手把手系列,不管是對于文本主題分類、多分類問題(犯罪類型分類) 還是 情感分析/分類,樸素貝葉斯都是一個簡單直接高效的方法。尤其是在和邏輯回歸的對比中可以看出,在這些問題中,樸素貝葉斯能取得和邏輯回歸相近的成績,但是訓練速度遠快于邏輯回歸,真正的直接和高效。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看