貝葉斯--舊金山犯罪分類預測和電影評價好壞 demo


來源引用:https://blog.csdn.net/han_xiaoyang/article/details/50629608

 

1、引言

貝葉斯是經典的機器學習算法,朴素貝葉斯經常運用於機器學習的案例。比如說

文本分類/垃圾郵件的分類/情感分析:在文本分類中,貝斯依舊占有一席之地,因為文本數據中,分布獨立這個假設基本上成立的。

推薦系統:朴素貝葉斯和協同過濾一起使用,經常出現在推薦系統。以后有機會會好好寫一篇關於推薦系統的文章。

值得提醒的,以下部分點是要知道的:

  • 數據要服從正態分布,
  • 使用拉普斯平滑來處理測試數據中的0頻次項
  • sklearn中的可調參數很少,只有拉普斯平滑因子alpha,類別先驗概率class_prior和預算數據類別先驗fit_prior。所以建議加強特征工程的操作來完善模型。
  • 集成方法對貝葉斯沒有用,因為集成方法是用來減少過擬合的,減少variance的,而貝葉斯沒有variance可以減少。

在sklearn中分為三類先驗:高斯分布,多項式分布,伯努利分布

這三個類適用的分類場景各不相同,一般來說,

  • 如果樣本特征的分布大部分是連續值,使用GaussianNB會比較好。
  • 如果如果樣本特征的分大部分是多元離散值,使用MultinomialNB比較合適。
  • 如果樣本特征是二元離散值或者很稀疏的多元離散值,應該使用BernoulliNB。

 

接下來分析下kaggle比賽里面的舊金山犯罪分類預測問題。

給出時間,地點,街區等特征來推測舊金山下一個犯罪類型是什么。

來做一個小小的demo

import pandas as pd
import numpy as np

#用pandas載入csv訓練數據,並解析第一列為日期格式
train=pd.read_csv('../input/train.csv', parse_dates = ['Dates'])
test=pd.read_csv('../input/test.csv', parse_dates = ['Dates'])
train

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)

#因子化星期幾,街區,小時等特征,就是one hot編碼
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

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 = ['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]))
#predict, predict_proba, predict_log_probas三種方法的區別
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]))
print("邏輯回歸建模耗時 %f 秒" %(lrCostTime)) print("邏輯回歸log損失為 %f" %(log_loss(validation['crime'], predicted)))

 

然后另一個經典應用是情感分析,kaggle類似的比賽就是 Bag of Words Meets Bags of Popcorn

給出各個用戶對電影的評價語句來判斷對該電影的評價是好還是壞。

我們知道DL的效果是好,但是耗時耗資源,貝葉斯建模快而且效果還可以。

首先我們explore下數據,train集數據包含三部分,分別是id,sentiment(好壞),review(內容),根據kaggle的官方指導,要對評論進行處理:去掉Html的標簽,‘/r’ 的處理,詞語轉化處理

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文件
# “header = 0”表示文件的第一行包含列名,“delimiter = \t”表示字段由制表符分隔,quoting = 3表示Python忽略雙引號,否則可能會遇到錯誤。
train = pd.read_csv('../input/labeledTrainData.tsv', header=0, delimiter="\t", quoting=3) test = pd.read_csv('../input/testData.tsv', header=0, delimiter="\t", quoting=3 ) # 取出情感標簽,positive/褒 或者 negative/貶 y_train = train['sentiment'] # 將訓練和測試數據都轉成詞list train_data = []
# xrange 用法與 range 完全相同,所不同的是生成的不是一個list對象,而是一個生成器。不用事先占用大內存。
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])))

 

接下來進行特征處理

評論經過上面的處理后還是一串字符串,要把它變成數字才好進行模型擬合。kaggle中的引導是使用word2vec的特征抽取方式,當然還有其它的特征抽取方法,比如說利用互信息的提取,有點類似決策樹的特征判斷。這里的話,使用sklearn的一種文本檢索有效的方法:TF-IDF向量法。該方法會把電影評論轉化成一個TF-IDF向量。簡要的解釋是,TF-IDF是一種統計方法,用以評估一字詞(或者n-gram)對於一個文件集或一個語料庫中的其中一份文件的重要程度。字詞的重要性隨着它在文件中出現的次數成正比增加,但同時會隨着它在語料庫中出現的頻率成反比下降。

以下是在sklearn的具體解釋,以后會整理出具體的用法:

http://sklearn.apachecn.org/cn/0.19.0/modules/feature_extraction.html#text-feature-extraction

具體以下代碼是去掉停用詞,在單詞級別上拓展到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:]

 

邏輯回歸和貝葉斯模型擬合:

# 多項式朴素貝葉斯
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}]

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM