sklearn 增量學習 數據量大

問題

實際處理和解決機器學習問題過程當中,咱們會遇到一些「大數據」問題,好比有上百萬條數據,上千上萬維特徵,此時數據存儲已經達到10G這種級別。這種狀況下,若是仍是直接使用傳統的方式確定行不通,好比當你想把數據load到內存中轉成numpy數組,你會發現要麼建立不了那麼大的numpy矩陣,要麼直接加載時報MemeryError。 
在這種狀況下我瞭解了幾種選擇辦法,1. 對數據進行降維,2. 使用流式或相似流式處理,3. 上大機器,高內存的,或者用spark集羣。html

文檔

Sklearn裏面提供一些流式處理方法。具體能夠參考官方文檔: 
講解了怎麼處理 big data 文件:http://scikit-learn.org/stable/modules/scaling_strategies.html 
經過一個例子講解了怎麼用:http://scikit-learn.org/stable/auto_examples/applications/plot_out_of_core_classification.html算法

簡單介紹

我看了上面兩個文檔,並使用介紹的SGDClassifier進行分類,效果挺好的,這裏記錄下用法。 
要實現big data的處理,須要知足三個條件: 
1. 有流式數據 
2. 能從數據中能夠提取出特徵 
3. 增量學習算法數組

1. 流式數據

第一個條件,要給算法流式數據或小batch的數據,好比一次提供1000條這樣。這一塊是須要本身寫代碼提供的,能夠實現一個生成器,每調用一次提供一份小batch數據。app

2. 提取特徵

第二個條件,可使用任何一種sklearn中支持的特徵提取方法。對於一些特殊狀況,好比特徵須要標準化或者是事先不知道特徵值的狀況下須要特殊處理。機器學習

3. 增量學習算法

對於第三個條件,sklearn中提供了不少增量學習算法。雖然不是全部的算法均可以增量學習,可是學習器提供了 partial_fit的函數的均可以進行增量學習。事實上,使用小batch的數據中進行增量學習(有時候也稱爲online learning)是這種學習方式的核心,由於它能讓任何一段時間內內存中只有少許的數據。 
sklearn提供不少增量學習算法:函數

  • Classification 
    • sklearn.naive_bayes.MultinomialNB
    • sklearn.naive_bayes.BernoulliNB
    • sklearn.linear_model.Perceptron
    • sklearn.linear_model.SGDClassifier
    • sklearn.linear_model.PassiveAggressiveClassifier
  • Regression 
    • sklearn.linear_model.SGDRegressor
    • sklearn.linear_model.PassiveAggressiveRegressor
  • Clustering 
    • sklearn.cluster.MiniBatchKMeans
  • Decomposition / feature Extraction 
    • sklearn.decomposition.MiniBatchDictionaryLearning
    • sklearn.decomposition.IncrementalPCA
    • sklearn.decomposition.LatentDirichletAllocation
    • sklearn.cluster.MiniBatchKMeans

其中對於分類問題,在第一次調用partial_fit時須要經過classes參數指定分類的類別。 
另外有一點須要考慮,全部的學習器在學習過程當中不會對每一個樣例賦予一樣的權重。對於感知機,它對於bad樣本會敏感,即便學習器已經學習了不少樣本了,而對於SGD和PassiveAggressive,對於這種狀況會更魯棒一點,後者在學習的時候,後來學習樣本的權重會隨着學習器學習率的降低而下降。學習

實例

這裏舉一個實際的例子。我這邊有上G的訓練文件和測試文件,都是csv格式。由於無法直接都讀進內存處理,因此選擇增量學習的方式處理。測試

1. 生成一個文件流迭代器

 1 def iter_minibatches(data_stream, minibatch_size=1000):
 2     '''
 3     迭代器
 4     給定文件流(好比一個大文件),每次輸出minibatch_size行,默認選擇1k行
 5     將輸出轉化成numpy輸出,返回X, y
 6     '''
 7     X = []
 8     y = []
 9     cur_line_num = 0
10 
11     csvfile = file(data_stream, 'rb')
12     reader = csv.reader(csvfile)
13     for line in reader:
14         y.append(float(line[0]))
15         X.append(line[1:])  # 這裏要將數據轉化成float類型
16 
17         cur_line_num += 1
18         if cur_line_num >= minibatch_size:
19             X, y = np.array(X), np.array(y)  # 將數據轉成numpy的array類型並返回
20             yield X, y
21             X, y = [], []
22             cur_line_num = 0
23     csvfile.close()
24 
25 # 生成測試文件
26 minibatch_test_iterators = iter_minibatches(test_file, minibatch_size=5000)
27 X_test, y_test = minibatch_test_iterators.next()  # 獲得一份測試文件

 

2. 增量訓練

1 from sklearn.linear_model import SGDClassifier
2 sgd_clf = SGDClassifier()  # SGDClassifier的參數設置能夠參考sklearn官網
3 minibatch_train_iterators = iter_minibatches(data_part_file, minibatch_size=2000)
4 
5 for i, (X_train, y_train) in enumerate(minibatch_train_iterators):
6     # 使用 partial_fit ,並在第一次調用 partial_fit 的時候指定 classes
7     sgd_clf.partial_fit(X_train, y_train, classes=np.array([0, 1]))
8     print("{} time".format(i))  # 當前次數
9     print("{} score".format(sgd_clf.score(X_test, y_test)))  # 在測試集上看效果

 

3. 結果

0 time
0.679 score
1 time
0.6954 score
2 time
0.712 score
3 time
0.7248 score
...
57 time
0.745 score
58 time
0.7394 score
59 time
0.7398 score

 

4. 一點補充

  1. 當SGD的損失函數爲log時,SGD等價於LR。
  2. 數據只迭代一次分類器可能還沒徹底收斂,能夠多迭代幾回
  3. mini-batch的量不要設置過小,過小的話,須要多迭代幾回才能收斂
相關文章
相關標籤/搜索