Query意圖分析:記一次完整的機器學習過程(scikit learn library學習筆記)

所謂學習問題,是指觀察由n個樣本組成的集合,并根據這些數據來預測未知數據的性質。

學習任務(一個二分類問題):

區分一個普通的互聯網檢索Query是否具有某個垂直領域的意圖。假設現在有一個O2O領域的垂直搜索引擎,專門為用戶提供團購、優惠券的檢索;同時存在一個通用的搜索引擎,比如百度,通用搜索引擎希望能夠識別出一個Query是否具有O2O檢索意圖,如果有則調用O2O垂直搜索引擎,獲取結果作為通用搜索引擎的結果補充。

我們的目的是學習出一個分類器(classifier),分類器可以理解為一個函數,其輸入為一個Query,輸出為0(表示該Query不具有o2o意圖)或1(表示該Query具有o2o意圖)。

特征提取

要完成這樣一個學習任務,首先我們必須找出決定一個Query是否具有O2O意圖的影響因素,這些影響因素稱之為特征(feature)。特征的好壞很大程度上決定了分類器的效果。在機器學習領域我們都知道特征比模型(學習算法)更重要。(順便說一下,工業界的人都是這么認為的,學術界的人可能不以為然,他們整天搗鼓算法,發出來的文章大部分都沒法在實際中應用。)舉個例子,如果我們的特征選得很好,可能我們用簡單的規則就能判斷出最終的結果,甚至不需要模型。比如,要判斷一個人是男還是女(人類當然很好判斷,一看就知道,這里我們假設由計算機來完成這個任務,計算機有很多傳感器(攝像頭、體重器等等)可以采集到各種數據),我們可以找到很多特征:身高、體重、皮膚顏色、頭發長度等等。因為根據統計我們知道男人一般比女人重,比女人高,皮膚比女人黑,頭發比女人短;所以這些特征都有一定的區分度,但是總有反例存在。我們用最好的算法可能準確率也達不到100%。假設計算機還能夠讀取人的身份證號碼,那么我們可能獲得一個更強的特征:身份證號碼的倒數第二位是否是偶數。根據身份證編碼規則,我們知道男性的身份證號碼的倒數第二位是奇數,女生是偶數。因此,有了這個特征其他的特征都不需要了,而且我們的分類器也很簡單,不需要復雜的算法。

言歸正傳,對于O2O Query意圖識別這一學習任務,我們可以用的特征可能有:Query在垂直引擎里能夠檢索到的結果數量、Query在垂直引擎里能夠檢索到的結果的類目困惑度(perplexity)(檢索結果的類目越集中說明其意圖越強)、Query能否預測到特征的O2O商品類目、Query是否包含O2O產品詞或品牌詞、Query在垂直引擎的歷史展現次數(PV)和點擊率(ctr)、Query在垂直引擎的檢索結果相關性等等。

特征表示

特征表示是對特征提取結果的再加工,目的是增強特征的表示能力,防止模型(分類器)過于復雜和學習困難。比如對連續的特征值進行離散化,就是一種常用的方法。這里我們以“Query在垂直引擎里能夠檢索到的結果數量”這一特征為例,簡要介紹一下特征值分段的過程。首先,分析一下這一維特征的分布情況,我們對這一維特征值的最小值、最大值、平均值、方差、中位數、三分位數、四分位數、某些特定值(比如零值)所占比例等等都要有一個大致的了解。獲取這些值,python編程語言的numpy模塊有很多現成的函數可以調用。最好的辦法就是可視化,借助python的matplotlib工具我們可以很容易地劃出數據分布的直方圖,從而判斷出我們應該對特征值劃多少個區間,每個區間的范圍是怎樣的。比如說我們要對“結果數量”這一維特征值除了“0”以為的其他值均勻地分為10個區間,即每個區間內的樣本數大致相同。“0”是一個特殊的值,因此我們想把它分到一個單獨的區間,這樣我們一共有11個區間。python代碼實現如下:

import numpy as npdef bin(bins):assert isinstance(bins, (list, tuple))def scatter(x):if x == 0: return 0for i in range(len(bins)):if x <= bins[i]: return i + 1return len(bins)return np.frompyfunc(scatter, 1, 1)data = np.loadtxt("D:\query_features.xls", dtype='int')
# descrete
o2o_result_num = data[:,0]
o2o_has_result = o2o_result_num[o2o_result_num > 0]
bins = [ np.percentile(o2o_has_result, x) for x in range(10, 101, 10) ]
data[:,0] = bin(bins)(o2o_result_num)

我們首先獲取每個區間的起止范圍,即分別算法特征向量的10個百分位數,并依此為基礎算出新的特征值(通過bin函數,一個numpy的universal function)。

訓練數據

這里我們通過有監督學習的方法來擬合分類器模型。所謂有監督學習是指通過提供一批帶有標注(學習的目標)的數據(稱之為訓練樣本),學習器通過分析數據的規律嘗試擬合出這些數據和學習目標間的函數,使得定義在訓練集上的總體誤差盡可能的小,從而利用學得的函數來預測未知數據的學習方法。注意這不是一個嚴格的定義,而是我根據自己的理解簡化出來的。

一批帶有標注的訓練數據從何而來,一般而言都需要人工標注。我們從搜索引擎的日志里隨機采集一批Query,并且保證這批Query能夠覆蓋到每維特征的每個取值(從這里也可以看出為什么要做特征分區間或離散化了,因為如不這樣做我們就不能保證能夠覆蓋到每維特征的每個取值)。然后,通過人肉的方法給這邊Query打上是否具有O2O意圖的標簽。數據標注是一個痛苦而漫長的過程,需要具有一定領域知識的人來干這樣的活。標注質量的好壞很有可能會影響到學習到的模型(這里指分類器)在未知Query上判別效果的好壞。即正確的老師更可能教出正確的學生,反之,錯誤的老師教壞學生的可能性越大。在我自己標注數據的過程中,發現有一些Query的O2O意圖比較模棱兩可,導致我后來回頭看的時候總覺得自己標得不對,反反復復修改了好幾次。

選擇模型

在我們的問題中,模型就是要學習的分類器。有監督學習的分類器有很多,比如決策樹、隨機森林、邏輯回歸、梯度提升、SVM等等。如何為我們的分類問題選擇合適的機器學習算法呢?當然,如果我們真正關心準確率,那么最佳方法是測試各種不同的算法(同時還要確保對每個算法測試不同參數),然后通過交叉驗證選擇最好的一個。但是,如果你只是為你的問題尋找一個“足夠好”的算法,或者一個起點,也是有一些還不錯的一般準則的,比如如果訓練集很小,那么高偏差/低方差分類器(如樸素貝葉斯分類器)要優于低偏差/高方差分類器(如k近鄰分類器),因為后者容易過擬合。然而,隨著訓練集的增大,低偏差/高方差分類器將開始勝出(它們具有較低的漸近誤差),因為高偏差分類器不足以提供準確的模型。

這里我們重點介紹一次完整的機器學習全過程,所以不花大篇幅在模型選擇的問題上,推薦大家讀一些這篇文章:《如何選擇機器學習分類器?》。

通過交叉驗證擬合模型

機器學習會學習數據集的某些屬性,并運用于新數據。這就是為什么習慣上會把數據分為兩個集合,由此來評價算法的優劣。這兩個集合,一個叫做訓練集(train data),我們從中獲得數據的性質;一個叫做測試集(test data),我們在此測試這些性質,即模型的準確率。將一個算法作用于一個原始數據,我們不可能只做出隨機的劃分一次train和test data,然后得到一個準確率,就作為衡量這個算法好壞的標準。因為這樣存在偶然性。我們必須好多次的隨機的劃分train data和test data,分別在其上面算出各自的準確率。這樣就有一組準確率數據,根據這一組數據,就可以較好的準確的衡量算法的好壞。交叉驗證就是一種在數據量有限的情況下的非常好evaluate performance的方法。

 1 from sklearn import cross_validation2 from sklearn import tree3 from sklearn import ensemble4 from sklearn import linear_model5 from sklearn import svm6 7 lr = linear_model.LogisticRegression()8 lr_scores = cross_validation.cross_val_score(lr, train_data, train_target, cv=5)9 print("logistic regression accuracy:")
10 print(lr_scores)
11 
12 clf = tree.DecisionTreeClassifier(criterion='entropy', max_depth=8, min_samples_split=5)
13 clf_scores = cross_validation.cross_val_score(clf, train_data, train_target, cv=5)
14 print("decision tree accuracy:")
15 print(clf_scores)
16 
17 rfc = ensemble.RandomForestClassifier(criterion='entropy', n_estimators=3, max_features=0.5, min_samples_split=5)
18 rfc_scores = cross_validation.cross_val_score(rfc, train_data, train_target, cv=5)
19 print("random forest accuracy:")
20 print(rfc_scores)
21 
22 etc = ensemble.ExtraTreesClassifier(criterion='entropy', n_estimators=3, max_features=0.6, min_samples_split=5)
23 etc_scores = cross_validation.cross_val_score(etc, train_data, train_target, cv=5)
24 print("extra trees accuracy:")
25 print(etc_scores)
26 
27 gbc = ensemble.GradientBoostingClassifier()
28 gbc_scores = cross_validation.cross_val_score(gbc, train_data, train_target, cv=5)
29 print("gradient boosting accuracy:")
30 print(gbc_scores)
31 
32 svc = svm.SVC()
33 svc_scores = cross_validation.cross_val_score(svc, train_data, train_target, cv=5)
34 print("svm classifier accuracy:")
35 print(svc_scores)

上面的代碼我們嘗試同交叉驗證的方法對比五種不同模型的準確率,結果如下:

 1 logistic regression accuracy:2 [ 0.76953125  0.83921569  0.85433071  0.81102362  0.83858268]3 decision tree accuracy:4 [ 0.73828125  0.8         0.77559055  0.71653543  0.83464567]5 random forest accuracy:6 [ 0.75        0.76862745  0.76377953  0.77165354  0.80314961]7 extra trees accuracy:8 [ 0.734375    0.78039216  0.7992126   0.76377953  0.79527559]9 gradient boosting accuracy:
10 [ 0.7578125   0.81960784  0.83464567  0.80708661  0.84251969]
11 svm classifier accuracy:
12 [ 0.703125    0.78431373  0.77952756  0.77952756  0.80708661]

在O2O意圖識別這個學習問題上,邏輯回歸分類器具有最好的準確率,其次是梯度提升分類器;決策樹和隨機森林在我們的測試結果中并沒有體現出明顯的差異,可能是我們的特殊數量太少并且樣本數也較少的原因;另外大名典典的SVM的表現卻比較讓人失望。總體而言,準確率只有82%左右,分析其原因,一方面我們實現的特征數量較少;另一方面暫時未能實現區分能力強的特征。后續會對此持續優化。

由于邏輯回歸分類器具有最好的性能,我們決定用全部是可能訓練數據來擬合之。

lr = lr.fit(train_data, train_target)

模型數據持久化

學到的模型要能夠在將來利用起來,就必須把模型保存下來,以便下次使用。同時,數據離散化或數據分區的范圍數據也要保存下來,在預測的時候同樣也需要對特征進行區間劃分。python提供了pickle模塊用來序列號對象,并保存到硬盤上。同時,scikit-learn庫也提供了更加高效的模型持久化模塊,可以直接使用。

1 from sklearn.externals import joblib
2 joblib.dump(lr, 'D:\lr.model')
3 import pickle
4 bin_file = open(r'D:\result_bin.data', 'wb')
5 pickle.dump(bins, bin_file)
6 bin_file.close()

分類器的使用

現在大功告成了,我們需要做的就是用學習到的分類器來判斷一個新的Query到底是否具有O2O意圖。因為我們分類器的輸入是Query的特征向量,而不是Query本身,因此我們需要實現提取好Query的特征。假設我們已經離線算好了每個Query的特征,現在使用的時候只需要將其加載進內場即可。分類器使用的過程首先是從硬盤讀取模型數據和Query特征,然后調用模型對Query進行預測,輸出結果。

 1 # load result bin data and model2 bin_file = open(r'D:\result_bin.data', 'rb')3 bins = pickle.load(bin_file)4 bin_file.close()5 6 lr = joblib.load('D:\lr.model')7 8 # load data9 query = np.genfromtxt(r'D:\o2o_query_rec\all_query', dtype='U2', comments=None, converters={0: lambda x: str(x, 'utf-8')})
10 feature = np.loadtxt(r'D:\o2o_query_rec\all_features', dtype='int', delimiter='\001')
11 
12 # descrite
13 feature[:,0] = bin(bins)(feature[:,0])
14 feature[:,1] = ufunc_segment(feature[:,1])
15 
16 # predict
17 result = lr.predict(feature)
18 
19 # save result
20 #np.savetxt(r'D:\o2o_query_rec\classify_result.txt', np.c_[query, result], fmt=u"%s", delimiter="\t")
21 result_file = open(r'D:\o2o_query_rec\classify_result.txt', 'w')
22 i = 0
23 for q in query:
24     result_file.write('%s\t%d\n' % (q, result[i]))
25     i += 1
26 result_file.close()

需要注意的是我們Query的編碼是UTF-8,load的時候需要做相應的轉換。另外,在python 3.3版本,numpy的savetxt函數并不能正確保持UTF-8格式的中文Query(第20行注釋掉的代碼輸出的Query都變成了bytes格式的),如果小伙伴們有更好的辦法能夠解決這個問題,請告訴我,謝謝!

?

轉載于:https://www.cnblogs.com/DjangoBlog/p/6212911.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247455.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247455.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247455.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用 vue-cli 開發多頁應用

修改的webpack配置文件 全局配置 修改 webpack.base.conf.js 打開 ~\build\webpack.base.conf.js ,找到entry,添加多入口 entry: {app: ./src/main.js,app2: ./src/main2.js,app3: ./src/main3.js, }, 運行、編譯的時候每一個入口都會對應一個Chunk …

深度學習系統相比較傳統的機器學習系統,針對常見的分類問題,精度究竟能有多大提升?...

來源:知乎原文鏈接:深度學習系統相比較傳統的機器學習系統,針對常見的分類問題,精度究竟能有多大提升? 問題: 我現在手頭有一個binary classification的問題。數據量在一百萬左右。每個sample都是一個14個f…

遠程鏈接錯誤:這可能是由于credssp加密oracle修正

此錯誤解決辦法 1.WinR 輸入regedit打開注冊表 找到對應的以下目錄HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System 此時如果System下沒有CredSSP時創建CredSSP沒有Parameters時,創建Parameters 創建方法:右建>>新建>>項 2.在Para…

SpringBoot入門最詳細教程

https://www.jianshu.com/p/af3d5800f763 網上有很多springboot的入門教程,自己也因為項目要使用springboot,所以利用業余時間自學了下springboot和springcloud,使用下來發現springboot還是挺簡單的,體現了極簡的編程風格&#xf…

通過Vue CLI3 快速創建Vue項目并部署到tomcat

1、前提 首先你要安裝好nodejs和yarn,直接在官網下載安裝包,一鍵安裝即可,不需要什么環境配置,我安裝的是最新版本(node-v10.13.0、yarn-1.12.3) 2、安裝 同時寫Vue CLI 3和Vue CLI 2 的原因是官方默認的是3&#x…

簡述區塊鏈(1)- 也許只有這一篇

一、嘮叨兩句 最近一直在考慮一個事情,就是怎么給不太了解技術的人講清楚區塊鏈。我先試著寫下來,然后在逐步打磨吧,目標就是讓哪些說看區塊鏈看的云里霧里的同學能對區塊鏈有一些認知。 二、定義 簡單的給區塊鏈下個定義:基于加密…

Vue CLI 3.0腳手架如何在本地配置mock數據json

前后端分離的開發模式已經是目前前端的主流模式,至于為什么會前后端分離的開發我們就不做過多的闡述,既然是前后端分離的模式開發肯定是離不開前端的數據模擬階段。 我們在開發的過程中,由于后臺接口的沒有完成或者沒有穩定之前我們都是采用…

python 通過下載包setup.py安裝模塊

下載安裝包,并解壓到相應的位置 1、打開cmd 2、到達安裝目錄 3、python setup.py build 4、python setup.py install 轉載于:https://www.cnblogs.com/liuchunxiao83/p/11207340.html

webpack之externals操作三部曲--正確的姿勢

1.作用 首先webpack提供這個externals選項作用是從打包的bundle文件中排除依賴。換句話說就是讓在項目中通過import引入的依賴在打包的時候不會打包到bundle包中去,而是通過script的方式去訪問這些依賴。 2.怎么用? 以jquery為例子,目的是在…

Anaconda3自帶jupyter

1、cmd命令行中輸入 JupyterNotebook 2、系統自動調起下面頁面(注冊端口沖突是打不開的) 轉載于:https://www.cnblogs.com/liuchunxiao83/p/11207385.html

python 的按位與 或 異或 運算

符號 描述 運算規則 by MoreWindows & 與 兩個位都為1時,結果才為1 (統計奇數) | 或 兩個位都為0時,結果才為0 (統計偶數) ^ 異或 兩…

理解Shadow DOM

1. 什么是Shadow DOM? Shadow DOM 如果按照英文翻譯的話可以理解為 影子DOM, 何為影子DOM呢?可以理解為一般情況下使用肉眼看不到的DOM結構,那如果一般情況下看不到的話,那也就是說我們無法直接控制操縱的DOM結構。 Shadow DOM 它是HTML的一…

046 實例11-自動軌跡繪制

目錄 一、"自動軌跡繪制"問題分析1.1 問題分析1.2 自動軌跡繪制二、"自動軌跡繪制"實例講解2.1 自動軌跡繪制2.2 數據接口定義2.3 數據文件三、"自動軌跡繪制"舉一反三3.1 理解方法思維3.2 應用問題的擴展一、"自動軌跡繪制"問題分析 …

bootstrap-select采坑

bootstrap-select采坑 1.class"selectpicker" 普通的下拉框功能 2.title"請選擇城市名稱" title的作用與palcehoder一樣。 3.select class"selectpicker" multiple selectpicker和multiple屬性的搭配使用可實現多選 4.data-live-search"tru…

對vue虛擬dom的研究

Vue.js通過編譯將template 模板轉換成渲染函數(render ) ,執行渲染函數就可以得到一個虛擬節點樹在對 Model 進行操作的時候,會觸發對應 Dep 中的 Watcher 對象。Watcher 對象會調用對應的 update 來修改視圖。這個過程主要是將新舊虛擬節點進行差異對比…

element-ui之dialog組件title插槽的使用

dialog對話框組件title屬性的slot使用方法 使用背景 需要單獨控制title中某個數據顯示及樣式&#xff0c;footer也一樣 <el-dialog// 也可以這樣寫,但是沒有辦法單獨控制name age的顯示// title"name age"title"提示":visible.sync"dialogVisi…

css3自適應布局單位vw,vh

視口單位(Viewport units) 什么是視口&#xff1f; 在桌面端&#xff0c;視口指的是在桌面端&#xff0c;指的是瀏覽器的可視區域&#xff1b;而在移動端&#xff0c;它涉及3個視口&#xff1a;Layout Viewport&#xff08;布局視口&#xff09;&#xff0c;Visual Viewport…

python 操作 elasticsearch-7.0.2 遇到的問題

錯誤一&#xff1a;TypeError: search() got an unexpected keyword argument doc_type&#xff0c;得到不預期外的參數 解決方法&#xff1a;elasticsearch7里不用文檔類型&#xff0c;所以去掉 doc_typecredit_data 錯誤二&#xff1a;RequestError(400, illegal_argument_ex…

用到的Shell

sed 1i 添加的內容 file #這是在第一行前添加字符串 sed $i 添加的內容 file #這是在最后一行行前添加字符串 sed $a添加的內容 file #這是在最后一行行后添加字符串 sed -i s/.*/行首添加內容&行尾添加內容/ 文件名 //每一行 sed -i $a新增的一行 tars_build_tar.sh a…

如何解決瀏覽器縮小出現橫向滾動條時網頁背景圖出現空白的問題

原因&#xff1a; 當窗口縮小時&#xff0c;瀏覽器默認100%寬度為瀏覽器窗口的寬度。而忽略了下部內容層固定寬度(1024px)。從而出現了固定寬度大于100%寬度的現象。瀏覽以此理解來解析頁面&#xff0c;就出現了容器寬度理解上的差異&#xff0c;出現了一個非常奇特的BUG。 解…