以使用JavaScript內置的`DOMParser`對象來實現類似于PHP中`html_entity_decode`函數的功能。以下是一個簡單的實現:
function html_entity_decode(str) {
var parser = new DOMParser();
var dom = parser.parseFromString('<!doctype html><body>' + str, 'text/html');
return dom.body.textContent;
}
這個函數接受一個字符串參數,將其中的HTML實體字符解碼為對應的字符,并返回解碼后的字符串。例如:
var str = 'This is a <b>test</b> string.';
var decodedStr = html_entity_decode(str);
console.log(decodedStr); // This is a <b>test</b> string.
這個實現方法并不完美,因為它只能解碼HTML實體字符,而不能解碼XML實體字符。如果需要解碼XML實體字符,可以使用第三方庫,例如he.js。
以上數據由#ch-a-t-G-PT#提供
ue.js設計與實現,文字可復制,高清PDF資源,需要的可以私我 :)
本書基于Vue.js 3,從規范出發,以源碼為基礎,并結合大量直觀的配圖,循序漸進地講解Vue.js中各個功能模塊的實現,細致剖析框架設計原理。全書共18章,分為六篇,主要內容包括:框架設計概覽、響應系統、渲染器、組件化、編譯器和服務端渲染等。通過閱讀本書,對Vue.js 2/3具有上手經驗的開發人員能夠進一步理解Vue.js框架的實現細節,沒有Vue.js使用經驗但對框架設計感興趣的前端開發人員,能夠快速掌握Vue.js的設計原理。
霍春陽(HcySunYang)
Vue.js官方團隊成員,專注于Web研發領域,是Vue.js 3的核心貢獻者之一,Vue.js文檔生成工具Vuese的作者,技術社區活躍者,曾撰寫大量頗受好評的技術博客。
第 1章 權衡的藝術 2
1.1 命令式和聲明式 2
1.2 性能與可維護性的權衡 3
1.3 虛擬DOM的性能到底如何 4
1.4 運行時和編譯時 8
1.5 總結 11
第 2章 框架設計的核心要素 12
2.1 提升用戶的開發體驗 12
2.2 控制框架代碼的體積 14
2.3 框架要做到良好的Tree-Shaking 15
2.4 框架應該輸出怎樣的構建產物 17
2.5 特性開關 19
2.6 錯誤處理 21
2.7 良好的TypeScript類型支持 23
2.8 總結 25
第3章 Vue.js 3的設計思路 27
3.1 聲明式地描述UI 27
3.2 初識渲染器 29
3.3 組件的本質 32
3.4 模板的工作原理 34
3.5 Vue.js是各個模塊組成的有機整體 36
3.6 總結 37
第4章 響應系統的作用與實現 40
4.1 響應式數據與副作用函數 40
4.2 響應式數據的基本實現 41
4.3 設計一個完善的響應系統 43
4.4 分支切換與cleanup 50
4.5 嵌套的effect與effect棧 55
4.6 避免無限遞歸循環 59
4.7 調度執行 60
4.8 計算屬性computed與lazy 64
4.9 watch的實現原理 71
4.10 立即執行的watch與回調執行時機 75
4.11 過期的副作用 77
4.12 總結 82
第5章 非原始值的響應式方案 84
5.1 理解Proxy和Reflect 84
5.2 JavaScript對象及Proxy的工作原理 88
5.3 如何代理Object 92
5.4 合理地觸發響應 102
5.5 淺響應與深響應 108
5.6 只讀和淺只讀 110
5.7 代理數組 113
5.7.1 數組的索引與 length 114
5.7.2 遍歷數組 119
5.7.3 數組的查找方法 124
5.7.4 隱式修改數組長度的原型方法 129
5.8 代理Set和Map 132
5.8.1 如何代理Set和Map 133
5.8.2 建立響應聯系 137
5.8.3 避免污染原始數據 140
5.8.4 處理forEach 143
5.8.5 迭代器方法 147
5.8.6 values與keys方法 152
5.9 總結 155
第6章 原始值的響應式方案 158
6.1 引入ref的概念 158
6.2 響應丟失問題 160
6.3 自動脫ref 164
6.4 總結 166
第7章 渲染器的設計 170
7.1 渲染器與響應系統的結合 170
7.2 渲染器的基本概念 172
7.3 自定義渲染器 175
7.4 總結 179
第8章 掛載與更新 180
8.1 掛載子節點和元素的屬性 180
8.2 HTML Attributes與DOM Properties 182
8.3 正確地設置元素屬性 184
8.4 class的處理 189
8.5 卸載操作 192
8.6 區分vnode的類型 195
8.7 事件的處理 196
8.8 事件冒泡與更新時機問題 201
8.9 更新子節點 204
8.10 文本節點和注釋節點 209
8.11 Fragment 212
8.12 總結 215
第9章 簡單Diff算法 218
9.1 減少DOM操作的性能開銷 218
9.2 DOM復用與key的作用 221
9.3 找到需要移動的元素 225
9.4 如何移動元素 228
9.5 添加新元素 233
9.6 移除不存在的元素 238
9.7 總結 241
第 10章 雙端Diff算法 242
10.1 雙端比較的原理 242
10.2 雙端比較的優勢 252
10.3 非理想狀況的處理方式 255
10.4 添加新元素 263
10.5 移除不存在的元素 268
10.6 總結 270
第 11章 快速Diff算法 271
11.1 相同的前置元素和后置元素 271
11.2 判斷是否需要進行DOM移動操作 279
11.3 如何移動元素 288
11.4 總結 296
第 12章 組件的實現原理 298
12.1 渲染組件 298
12.2 組件狀態與自更新 301
12.3 組件實例與組件的生命周期 304
12.4 props與組件的被動更新 306
12.5 setup函數的作用與實現 311
12.6 組件事件與emit的實現 314
12.7 插槽的工作原理與實現 316
12.8 注冊生命周期 318
12.9 總結 320
第 13章 異步組件與函數式組件 322
13.1 異步組件要解決的問題 322
13.2 異步組件的實現原理 324
13.2.1 封裝defineAsyncComponent函數 324
13.2.2 超時與Error組件 325
13.2.3 延遲與Loading組件 328
13.2.4 重試機制 331
13.3 函數式組件 333
13.4 總結 335
第 14章 內建組件和模塊 337
14.1 KeepAlive組件的實現原理 337
14.1.1 組件的激活與失活 337
14.1.2 include和exclude 342
14.1.3 緩存管理 343
14.2 Teleport組件的實現原理 346
14.2.1 Teleport組件要解決的問題 346
14.2.2 實現Teleport組件 347
14.3 Transition組件的實現原理 350
14.3.1 原生DOM的過渡 351
14.3.2 實現Transition組件 356
14.4 總結 360
第 15章 編譯器核心技術概覽 364
15.1 模板DSL的編譯器 364
15.2 parser的實現原理與狀態機 368
15.3 構造AST 374
15.4 AST的轉換與插件化架構 383
15.4.1 節點的訪問 383
15.4.2 轉換上下文與節點操作 387
15.4.3 進入與退出 392
15.5 將模板AST轉為JavaScript AST 396
15.6 代碼生成 402
15.7 總結 407
第 16章 解析器 409
16.1 文本模式及其對解析器的影響 409
16.2 遞歸下降算法構造模板AST 413
16.3 狀態機的開啟與停止 419
16.4 解析標簽節點 426
16.5 解析屬性 430
16.6 解析文本與解碼HTML實體 436
16.6.1 解析文本 436
16.6.2 解碼命名字符引用 438
16.6.3 解碼數字字符引用 445
16.7 解析插值與注釋 449
16.8 總結 451
第 17章 編譯優化 453
17.1 動態節點收集與補丁標志 453
17.1.1 傳統Diff算法的問題 453
17.1.2 Block與PatchFlags 454
17.1.3 收集動態節點 457
17.1.4 渲染器的運行時支持 459
17.2 Block樹 461
17.2.1 帶有v-if指令的節點 462
17.2.2 帶有v-for指令的節點 464
17.2.3 Fragment的穩定性 465
17.3 靜態提升 466
17.4 預字符串化 468
17.5 緩存內聯事件處理函數 469
17.6 v-once 470
17.7 總結 471
第 18章 同構渲染 474
18.1 CSR、SSR以及同構渲染 474
18.2 將虛擬DOM渲染為HTML字符串 478
18.3 將組件渲染為HTML字符串 484
18.4 客戶端激活的原理 489
18.5 編寫同構的代碼 494
18.5.1 組件的生命周期 494
18.5.2 使用跨平臺的API 496
18.5.3 只在某一端引入模塊 496
18.5.4 避免交叉請求引起的狀態污染 497
18.5.5 組件 498
18.6 總結 499
Vue.js設計與實現,文字可復制,高清PDF資源,需要的可以私我 :)
文是 2014 年 12 月我在布拉格經濟大學做的名為‘ Python 數據科學’講座的筆記。歡迎提問和評論。
本次講座的目的是展示一些關于機器學習的高級概念。該筆記中用具體的代碼來做演示,大家可以在自己的電腦上運行(需要安裝 IPython,如下所示)。
本次講座的聽眾需要了解一些基礎的編程(不一定是 Python),并擁有一點基本的數據挖掘背景。本次講座不是機器學習專家的“高級演講”。
這些代碼實例創建了一個有效的、可執行的原型系統:一個使用“spam”(垃圾信息)或“ham”(非垃圾信息)對英文手機短信(”短信類型“的英文)進行分類的 app。
整套代碼使用 Python 語言。 python 是一種在管線(pipeline)的所有環節(I/O、數據清洗重整和預處理、模型訓練和評估)都好用的通用語言。盡管 python 不是唯一選擇,但它靈活、易于開發,性能優越,這得益于它成熟的科學計算生態系統。Python 龐大的、開源生態系統同時避免了任何單一框架或庫的限制(以及相關的信息丟失)。
IPython notebook,是 Python 的一個工具,它是一個以 HTML 形式呈現的交互環境,可以通過它立刻看到結果。我們也將重溫其它廣泛用于數據科學領域的實用工具。
想交互運行下面的例子(選讀)?
安裝免費的 Anaconda Python 發行版,其中已經包含 Python 本身。
安裝“自然語言處理”庫——TextBlob:安裝包在這。
下載本文的源碼(網址:http://radimrehurek.com/data_science_python/data_science_python.ipynb 并運行:$ ipython notebook data_science_python.ipynb
觀看 IPython notebook 基本用法教程 IPython tutorial video 。
運行下面的第一個代碼,如果執行過程沒有報錯,就可以了。
端到端的例子:自動過濾垃圾信息
In [1]:
%matplotlibinline
importmatplotlib.pyplot asplt
importcsv
fromtextblob importTextBlob
importpandas
importsklearn
importcPickle
importnumpy asnp
fromsklearn.feature_extraction.text importCountVectorizer,TfidfTransformer
fromsklearn.naive_bayes importMultinomialNB
fromsklearn.svm importSVC,LinearSVC
fromsklearn.metrics importclassification_report,f1_score,accuracy_score,confusion_matrix
fromsklearn.pipeline importPipeline
fromsklearn.grid_search importGridSearchCV
fromsklearn.cross_validation importStratifiedKFold,cross_val_score,train_test_split
fromsklearn.tree importDecisionTreeClassifier
fromsklearn.learning_curve importlearning_curve
第一步:加載數據,瀏覽一下
讓我們跳過真正的第一步(完善資料,了解我們要做的是什么,這在實踐過程中是非常重要的),直接到 https://archive.ics.uci.edu/ml/datasets/SMS+Spam+Collection 下載 demo 里需要用的 zip 文件,解壓到 data 子目錄下。你能看到一個大概 0.5MB 大小,名為 SMSSpamCollection 的文件:
$ <span class="kw">ls</span> -ldata
<span class="kw">total</span> 1352
<span class="kw">-rw-r--r--@</span> 1kofola staff477907Mar152011SMSSpamCollection
<span class="kw">-rw-r--r--@</span> 1kofola staff5868Apr182011readme
<span class="kw">-rw-r-----@</span> 1kofola staff203415Dec115:30smsspamcollection.zip
這份文件包含了 5000 多份 SMS 手機信息(查看 readme 文件以獲得更多信息):
In [2]:
messages = [line.rstrip()forline inopen('./data/SMSSpamCollection')]
print len(messages)
5574
文本集有時候也稱為“語料庫”,我們來打印 SMS 語料庫中的前 10 條信息:
In [3]:
formessage_no,message inenumerate(messages[:10]):
printmessage_no,message
0ham Go until jurong point,crazy..Available only inbugisngreat world laebuffet...Cine there got amore wat...
1ham Ok lar...Joking wifuoni...
2spam Free entry in2awkly comp to win FA Cup final tkts21stMay2005.Text FA to87121to receive entry question(std txt rate)T&C's apply 08452810075over18's
3hamUdun say so early hor...Ucalready then say...
4ham NahIdon't think he goes to usf, he lives around here though
5 spam FreeMsg Hey there darling it'sbeen3week's now and no word back! I'dlike some fun you up forit still?Tb ok!XxX std chgs to send,£1.50to rcv
6ham Even my brother isnotlike to speak withme.They treat me like aids patent.
7ham Asper your request'Melle Melle (Oru Minnaminunginte Nurungu Vettam)'has been setasyour callertune forallCallers.Press *9to copyyour friends Callertune
8spam WINNER!! Asavalued network customer you have been selected to receivea£900prize reward! To claim call09061701461.Claim codeKL341.Valid12hours only.
9spam Had your mobile11months ormore?URentitled to Update to the latest colour mobiles withcamera forFree! Call The Mobile Update Co FREE on08002986030
我們看到一個 TSV 文件(用制表符 tab 分隔),它的第一列是標記正常信息(ham)或“垃圾文件”(spam)的標簽,第二列是信息本身。
這個語料庫將作為帶標簽的訓練集。通過使用這些標記了 ham/spam 例子,我們將訓練一個自動分辨 ham/spam 的機器學習模型。然后,我們可以用訓練好的模型將任意未標記的信息標記為 ham 或 spam。
我們可以使用 Python 的 Pandas 庫替我們處理 TSV 文件(或 CSV 文件,或 Excel 文件):
In [4]:
messages = pandas.read_csv('./data/SMSSpamCollection',sep='t',quoting=csv.QUOTE_NONE,
names=["label","message"])
printmessages
我們也可以使用 pandas 輕松查看統計信息:
In [5]:
messages.groupby('label').describe()
out[5]:
這些信息的長度是多少:
In [6]:
messages['length'] = messages['message'].map(lambdatext: len(text))
printmessages.head()
In [7]:
messages.length.plot(bins=20, kind='hist')
Out[7]:
<matplotlib.axes._subplots.AxesSubplot at 0x10dd7a990>
In [8]:
messages.length.describe()
Out[8]:
哪些是超長信息?
In [9]:
print list(messages.message[messages.length > 900])
spam 信息與 ham 信息在長度上有區別嗎?
In [10]:
messages.hist(column='length', by='label', bins=50)
Out[10]:
array([<matplotlib.axes._subplots.AxesSubplot object at 0x11270da50>,
<matplotlib.axes._subplots.AxesSubplot object at 0x1126c7750>], dtype=object)
太棒了,但是我們怎么能讓電腦自己識別文字信息?它可以理解這些胡言亂語嗎?
第二步:數據預處理
這一節我們將原始信息(字符序列)轉換為向量(數字序列);
這里的映射并非一對一的,我們要用詞袋模型(bag-of-words)把每個不重復的詞用一個數字來表示。
與第一步的方法一樣,讓我們寫一個將信息分割成單詞的函數:
In [11]:
defsplit_into_tokens(message):
message = unicode(message,'utf8')# convert bytes into proper unicode
returnTextBlob(message).words
這還是原始文本的一部分:
In [12]:
messages.message.head()
Out[12]:
這是原始文本處理后的樣子:
In [13]:
messages.message.head().apply(split_into_tokens)
Out[13]:
自然語言處理(NLP)的問題:
大寫字母是否攜帶信息?
單詞的不同形式(“goes”和“go”)是否攜帶信息?
嘆詞和限定詞是否攜帶信息?
換句話說,我們想對文本進行更好的標準化。
我們使用 textblob 獲取 part-of-speech (POS) 標簽:
In [14]:
TextBlob("Hello world, how is it going?").tags # list of (word, POS) pairs
Out[14]:
并將單詞標準化為基本形式 (lemmas):
In [15]:
Out[15]:
這樣就好多了。你也許還會想到更多的方法來改進預處理:解碼 HTML 實體(我們上面看到的 & 和 <);過濾掉停用詞 (代詞等);添加更多特征,比如所有字母大寫標識等等。
第三步:數據轉換為向量
現在,我們將每條消息(詞干列表)轉換成機器學習模型可以理解的向量。
用詞袋模型完成這項工作需要三個步驟:
1. 對每個詞在每條信息中出現的次數進行計數(詞頻);
2. 對計數進行加權,這樣經常出現的單詞將會獲得較低的權重(逆向文件頻率);
3. 將向量由原始文本長度歸一化到單位長度(L2 范式)。
每個向量的維度等于 SMS 語料庫中包含的獨立詞的數量。
In [16]:
bow_transformer = CountVectorizer(analyzer=split_into_lemmas).fit(messages['message'])
printlen(bow_transformer.vocabulary_)
8874
這里我們使用強大的 python 機器學習訓練庫 scikit-learn (sklearn),它包含大量的方法和選項。
我們取一個信息并使用新的 bow_tramsformer 獲取向量形式的詞袋模型計數:
In [17]:
message4 = messages['message'][3]
printmessage4
U dun say so early hor... U c already then say...
In [18]:
bow4 = bow_transformer.transform([message4])
printbow4
printbow4.shape
message 4 中有 9 個獨立詞,它們中的兩個出現了兩次,其余的只出現了一次。可用性檢測,哪些詞出現了兩次?
In [19]:
printbow_transformer.get_feature_names()[6736]
printbow_transformer.get_feature_names()[8013]
say
u
整個 SMS 語料庫的詞袋計數是一個龐大的稀疏矩陣:
In [20]:
messages_bow = bow_transformer.transform(messages['message'])
print'sparse matrix shape:',messages_bow.shape
print'number of non-zeros:',messages_bow.nnz
print'sparsity: %.2f%%' % (100.0 * messages_bow.nnz / (messages_bow.shape[0] * messages_bow.shape[1]))
最終,計數后,使用 scikit-learn 的 TFidfTransformer 實現的 TF-IDF 完成詞語加權和歸一化。
In [21]:
單詞 “u” 的 IDF(逆向文件頻率)是什么?單詞“university”的 IDF 又是什么?
In [22]:
將整個 bag-of-words 語料庫轉化為 TF-IDF 語料庫。
In [23]:
有許多方法可以對數據進行預處理和向量化。這兩個步驟也可以稱為“特征工程”,它們通常是預測過程中最耗時間和最無趣的部分,但是它們非常重要并且需要經驗。訣竅在于反復評估:分析模型誤差,改進數據清洗和預處理方法,進行頭腦風暴討論新功能,評估等等。
第四步:訓練模型,檢測垃圾信息
我們使用向量形式的信息來訓練 spam/ham 分類器。這部分很簡單,有很多實現訓練算法的庫文件。
這里我們使用 scikit-learn,首先選擇 Naive Bayes 分類器:
In [24]:
我們來試著分類一個隨機信息:
In [25]:
太棒了!你也可以用自己的文本試試。
有一個很自然的問題是:我們可以正確分辨多少信息?
In [26]:
In [27]:
print'accuracy',accuracy_score(messages['label'],all_predictions)
print'confusion matrixn',confusion_matrix(messages['label'],all_predictions)
print'(row=expected, col=predicted)'
In [28]:
plt.matshow(confusion_matrix(messages['label'],all_predictions),cmap=plt.cm.binary,interpolation='nearest')
plt.title('confusion matrix')
plt.colorbar()
plt.ylabel('expected label')
plt.xlabel('predicted label')
Out[28]:
<matplotlib.text.Text at 0x11643f6d0>
我們可以通過這個混淆矩陣計算精度(precision)和召回率(recall),或者它們的組合(調和平均值)F1:
In [29]:
有相當多的指標都可以用來評估模型性能,至于哪個最合適是由任務決定的。比如,將“spam”錯誤預測為“ham”的成本遠低于將“ham”錯誤預測為“spam”的成本。
第五步:如何進行實驗?
在上述“評價”中,我們犯了個大忌。為了簡單的演示,我們使用訓練數據進行了準確性評估。永遠不要評估你的訓練數據。這是錯誤的。
這樣的評估方法不能告訴我們模型的實際預測能力,如果我們記住訓練期間的每個例子,訓練的準確率將非常接近 100%,但是我們不能用它來分類任何新信息。
一個正確的做法是將數據分為訓練集和測試集,在模型擬合和調參時只能使用訓練數據,不能以任何方式使用測試數據,通過這個方法確保模型沒有“作弊”,最終使用測試數據評價模型可以代表模型真正的預測性能。
In [30]:
按照要求,測試數據占整個數據集的 20%(總共 5574 條記錄中的 1115 條),其余的是訓練數據(5574 條中的 4459 條)。
讓我們回顧整個流程,將所有步驟放入 scikit-learn 的 Pipeline 中:
In [31]:
實際當中一個常見的做法是將訓練集再次分割成更小的集合,例如,5 個大小相等的子集。然后我們用 4 個子集訓練數據,用最后 1 個子集計算精度(稱之為“驗證集”)。重復5次(每次使用不同的子集進行驗證),這樣可以得到模型的“穩定性“。如果模型使用不同子集的得分差異非常大,那么很可能哪里出錯了(壞數據或者不良的模型方差)。返回,分析錯誤,重新檢查輸入數據有效性,重新檢查數據清洗。
在這個例子里,一切進展順利:
In [32]:
得分確實比訓練全部數據時差一點點( 5574 個訓練例子中,準確性 0.97),但是它們相當穩定:
In [33]:
我們自然會問,如何改進這個模型?這個得分已經很高了,但是我們通常如何改進模型呢?
Naive Bayes 是一個高偏差-低方差的分類器(簡單且穩定,不易過度擬合)。與其相反的例子是低偏差-高方差(容易過度擬合)的 k 最臨近(kNN)分類器和決策樹。Bagging(隨機森林)是一種通過訓練許多(高方差)模型和求均值來降低方差的方法。
換句話說:
高偏差 = 分類器比較固執。它有自己的想法,數據能夠改變的空間有限。另一方面,也沒有多少過度擬合的空間(左圖)。
低偏差 = 分類器更聽話,但也更神經質。大家都知道,讓它做什么就做什么可能造成麻煩(右圖)。
In [34]:
In [35]:
%time plot_learning_curve(pipeline, "accuracy vs. training set size", msg_train, label_train, cv=5)
CPU times: user382ms,sys: 83.1ms,total: 465ms
Wall time: 28.5s
Out[35]:
<module 'matplotlib.pyplot' from '/Volumes/work/workspace/vew/sklearn_intro/lib/python2.7/site-packages/matplotlib/pyplot.pyc'>
(我們對數據的 64% 進行了有效訓練:保留 20% 的數據作為測試集,保留剩余的 20% 做 5 折交叉驗證 = > 0.8*0.8*5574 = 3567個訓練數據。)
隨著性能的提升,訓練和交叉驗證都表現良好,我們發現由于數據量較少,這個模型難以足夠復雜/靈活地捕獲所有的細微差別。在這種特殊案例中,不管怎樣做精度都很高,這個問題看起來不是很明顯。
關于這一點,我們有兩個選擇:
使用更多的訓練數據,增加模型的復雜性;
使用更復雜(更低偏差)的模型,從現有數據中獲取更多信息。
在過去的幾年里,隨著收集大規模訓練數據越來越容易,機器越來越快。方法 1 變得越來越流行(更簡單的算法,更多的數據)。簡單的算法(如 Naive Bayes)也有更容易解釋的額外優勢(相對一些更復雜的黑箱模型,如神經網絡)。
了解了如何正確地評估模型,我們現在可以開始研究參數對性能有哪些影響。
第六步:如何調整參數?
到目前為止,我們看到的只是冰山一角,還有許多其它參數需要調整。比如使用什么算法進行訓練。
上面我們已經使用了 Navie Bayes,但是 scikit-learn 支持許多分類器:支持向量機、最鄰近算法、決策樹、Ensamble 方法等…
我們會問:IDF 加權對準確性有什么影響?消耗額外成本進行詞形還原(與只用純文字相比)真的會有效果嗎?
讓我們來看看:
In [37]:
In [38]:
%timenb_detector = grid.fit(msg_train,label_train)
printnb_detector.grid_scores_
CPU times: user4.09s,sys: 291ms,total: 4.38s
Wall time: 20.2s
[mean: 0.94752,std: 0.00357,params: {'tfidf__use_idf': True,'bow__analyzer': <function split_into_lemmas at0x1131e8668>},mean: 0.92958,std: 0.00390,params: {'tfidf__use_idf': False,'bow__analyzer': <function split_into_lemmas at0x1131e8668>},mean: 0.94528,std: 0.00259,params: {'tfidf__use_idf': True,'bow__analyzer': <function split_into_tokens at0x11270b7d0>},mean: 0.92868,std: 0.00240,params: {'tfidf__use_idf': False,'bow__analyzer': <function split_into_tokens at0x11270b7d0>}]
(首先顯示最佳參數組合:在這個案例中是使用 idf=True 和 analyzer=split_into_lemmas 的參數組合)
快速合理性檢查
In [39]:
predict_proba 返回每類(ham,spam)的預測概率。在第一個例子中,消息被預測為 ham 的概率 >99%,被預測為 spam 的概率 <1%。如果進行選擇模型會認為信息是 ”ham“:
In [40]:
在訓練期間沒有用到的測試集的整體得分:
In [41]:
這是我們使用詞形還原、TF-IDF 和 Navie Bayes 分類器的 ham 檢測 pipeline 獲得的實際預測性能。
讓我們嘗試另一個分類器:支持向量機(SVM)。SVM 可以非常迅速的得到結果,它所需要的參數調整也很少(雖然比 Navie Bayes 稍多一點),在處理文本數據方面它是個好的起點。
In [42]:
pipeline_svm = Pipeline([
('bow',CountVectorizer(analyzer=split_into_lemmas)),
('tfidf',TfidfTransformer()),
('classifier',SVC()),# <== change here
])
# pipeline parameters to automatically explore and tune
param_svm = [
{'classifier__C': [1,10,100,1000],'classifier__kernel': ['linear']},
{'classifier__C': [1,10,100,1000],'classifier__gamma': [0.001,0.0001],'classifier__kernel': ['rbf']},
]
grid_svm = GridSearchCV(
pipeline_svm,# pipeline from above
param_grid=param_svm,# parameters to tune via cross validation
refit=True,# fit using all data, on the best detected classifier
n_jobs=-1,# number of cores to use for parallelization; -1 for "all cores"
scoring='accuracy',# what score are we optimizing?
cv=StratifiedKFold(label_train,n_folds=5),# what type of cross validation to use
)
In [43]:
%timesvm_detector = grid_svm.fit(msg_train,label_train)# find the best combination from param_svm
printsvm_detector.grid_scores_
CPU times: user5.24s,sys: 170ms,total: 5.41s
Wall time: 1min8s
[mean: 0.98677,std: 0.00259,params: {'classifier__kernel': 'linear','classifier__C': 1},mean: 0.98654,std: 0.00100,params: {'classifier__kernel': 'linear','classifier__C': 10},mean: 0.98654,std: 0.00100,params: {'classifier__kernel': 'linear','classifier__C': 100},mean: 0.98654,std: 0.00100,params: {'classifier__kernel': 'linear','classifier__C': 1000},mean:0.86432,std: 0.00006,params: {'classifier__gamma': 0.001,'classifier__kernel': 'rbf','classifier__C': 1},mean: 0.86432,std:0.00006,params: {'classifier__gamma': 0.0001,'classifier__kernel': 'rbf','classifier__C': 1},mean: 0.86432,std: 0.00006,params: {'classifier__gamma': 0.001,'classifier__kernel': 'rbf','classifier__C': 10},mean: 0.86432,std: 0.00006,params:{'classifier__gamma': 0.0001,'classifier__kernel': 'rbf','classifier__C': 10},mean: 0.97040,std: 0.00587,params:{'classifier__gamma': 0.001,'classifier__kernel': 'rbf','classifier__C': 100},mean: 0.86432,std: 0.00006,params:{'classifier__gamma': 0.0001,'classifier__kernel': 'rbf','classifier__C': 100},mean: 0.98722,std: 0.00280,params:{'classifier__gamma': 0.001,'classifier__kernel': 'rbf','classifier__C': 1000},mean: 0.97040,std: 0.00587,params:{'classifier__gamma': 0.0001,'classifier__kernel': 'rbf','classifier__C': 1000}]
因此,很明顯的,具有 C=1 的線性核函數是最好的參數組合。
再一次合理性檢查:
In [44]:
In [45]:
這是我們使用 SVM 時可以從 spam 郵件檢測流程中獲得的實際預測性能。
第七步:生成預測器
經過基本分析和調優,真正的工作(工程)開始了。
生成預測器的最后一步是再次對整個數據集合進行訓練,以充分利用所有可用數據。當然,我們將使用上面交叉驗證找到的最好的參數。這與我們開始做的非常相似,但這次深入了解它的行為和穩定性。在不同的訓練/測試子集進行評價。
最終的預測器可以序列化到磁盤,以便我們下次想使用它時,可以跳過所有訓練直接使用訓練好的模型:
In [46]:
加載的結果是一個與原始對象表現相同的對象:
In [47]:
生產執行的另一個重要部分是性能。經過快速、迭代模型調整和參數搜索之后,性能良好的模型可以被翻譯成不同的語言并優化。可以犧牲幾個點的準確性換取一個更小、更快的模型嗎?是否值得優化內存使用情況,或者使用 mmap 跨進程共享內存?
請注意,優化并不總是必要的,要從實際情況出發。
還有一些需要考慮的問題,比如,生產流水線還需要考慮魯棒性(服務故障轉移、冗余、負載平衡)、監測(包括異常自動報警)、HR 可替代性(避免關于工作如何完成的“知識孤島”、晦澀/鎖定的技術、調整結果的黑藝術)。現在,開源世界都可以為所有這些領域提供可行的解決方法,由于 OSI 批準的開源許可證,今天展示的所有工具都可以免費用于商業用途。
其他實用概念
數據稀疏性
在線學習,數據流
用于內存共享的 mmap,系統“冷啟動”負載時間
可擴展性、分布式(集群)處理
無監督學習
大多數數據沒有結構化。了解這些數據,其中沒有自帶的標簽(不然就成了監督學習!)。
我們如何訓練沒有標簽的內容?這是什么魔法?
分布假設“在類似語境中出現的詞傾向于具有相似的含義”。上下文=句子,文檔,滑動窗口……
查看 google 關于無監督學習的 word2vec 在線演示。簡單的模型、大量數據(Google 新聞,1000 億詞,沒有標簽)。
下一步做什么?
這個 notebook 的靜態版本(非交互版本)的 HTML,地址: http://radimrehurek.com/data_science_python (你可能已經在看了,但以防萬一)
交互式 notebook 源文件在 GitHub 上,
http://radimrehurek.com/data_science_python/data_science_python.ipynb(見上面的安裝說明)。
End.
運行人員:中國統計網小編(微信號:itongjilove)
微博ID:中國統計網
中國統計網,是國內最早的大數據學習網站,公眾號:中國統計網
http://www.itongji.cn
*請認真填寫需求信息,我們會在24小時內與您取得聯系。