機(jī)器學(xué)習(xí)-sklearn-增量訓(xùn)練

問題

實(shí)際處理和解決機(jī)器學(xué)習(xí)問題過程中,我們會(huì)遇到一些“大數(shù)據(jù)”問題,比如有上百萬條數(shù)據(jù),上千上萬維特征,此時(shí)數(shù)據(jù)存儲(chǔ)已經(jīng)達(dá)到10G這種級(jí)別。這種情況下,如果還是直接使用傳統(tǒng)的方式肯定行不通,比如當(dāng)你想把數(shù)據(jù)load到內(nèi)存中轉(zhuǎn)成numpy數(shù)組,你會(huì)發(fā)現(xiàn)要么創(chuàng)建不了那么大的numpy矩陣,要么直接加載時(shí)報(bào)MemeryError。在這種情況下我了解了幾種選擇辦法,

  • 對(duì)數(shù)據(jù)進(jìn)行降維
  • 使用流式或類似流式處理
  • 上大機(jī)器,高內(nèi)存的,或者用spark集群。

文檔

Sklearn里面提供一些流式處理方法。具體可以參考官方文檔:
講解了怎么處理 big data 文件:http://scikit-learn.org/stable/modules/scaling_strategies.html
通過一個(gè)例子講解了怎么用:http://scikit-learn.org/stable/auto_examples/applications/plot_out_of_core_classification.html

簡(jiǎn)單介紹

我看了上面兩個(gè)文檔,并使用介紹的SGDClassifier進(jìn)行分類,效果挺好的,這里記錄下用法。
要實(shí)現(xiàn)big data的處理,需要滿足三個(gè)條件:
1 . 有流式數(shù)據(jù)
2 . 能從數(shù)據(jù)中可以提取出特征
3 . 增量學(xué)習(xí)算法

1. 流式數(shù)據(jù)

第一個(gè)條件,要給算法流式數(shù)據(jù)或小batch的數(shù)據(jù),比如一次提供1000條這樣。這一塊是需要自己寫代碼提供的,可以實(shí)現(xiàn)一個(gè)生成器,每調(diào)用一次提供一份小batch數(shù)據(jù)。

2. 提取特征

第二個(gè)條件,可以使用任何一種sklearn中支持的特征提取方法。對(duì)于一些特殊情況,比如特征需要標(biāo)準(zhǔn)化或者是事先不知道特征值的情況下需要特殊處理。

3. 增量學(xué)習(xí)算法

對(duì)于第三個(gè)條件,sklearn中提供了很多增量學(xué)習(xí)算法。雖然不是所有的算法都可以增量學(xué)習(xí),但是學(xué)習(xí)器提供了 partial_fit的函數(shù)的都可以進(jìn)行增量學(xué)習(xí)。事實(shí)上,使用小batch的數(shù)據(jù)中進(jìn)行增量學(xué)習(xí)(有時(shí)候也稱為online learning)是這種學(xué)習(xí)方式的核心,因?yàn)樗茏屓魏我欢螘r(shí)間內(nèi)內(nèi)存中只有少量的數(shù)據(jù)。
sklearn提供很多增量學(xué)習(xí)算法:

  • 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
      其中對(duì)于分類問題,在第一次調(diào)用partial_fit時(shí)需要通過classes參數(shù)指定分類的類別。
      另外有一點(diǎn)需要考慮,所有的學(xué)習(xí)器在學(xué)習(xí)過程中不會(huì)對(duì)每個(gè)樣例賦予同樣的權(quán)重。對(duì)于感知機(jī),它對(duì)于bad樣本會(huì)敏感,即使學(xué)習(xí)器已經(jīng)學(xué)習(xí)了很多樣本了,而對(duì)于SGD和PassiveAggressive,對(duì)于這種情況會(huì)更魯棒一點(diǎn),后者在學(xué)習(xí)的時(shí)候,后來學(xué)習(xí)樣本的權(quán)重會(huì)隨著學(xué)習(xí)器學(xué)習(xí)率的下降而降低。

實(shí)例

這里舉一個(gè)實(shí)際的例子。我這邊有上G的訓(xùn)練文件和測(cè)試文件,都是csv格式。因?yàn)闆]法直接都讀進(jìn)內(nèi)存處理,所以選擇增量學(xué)習(xí)的方式處理。

1. 生成一個(gè)文件流迭代器
def iter_minibatches(data_stream, minibatch_size=1000):
    '''
    迭代器
    給定文件流(比如一個(gè)大文件),每次輸出minibatch_size行,默認(rèn)選擇1k行
    將輸出轉(zhuǎn)化成numpy輸出,返回X, y
    '''
    X = []
    y = []
    cur_line_num = 0

    csvfile = file(data_stream, 'rb')
    reader = csv.reader(csvfile)
    for line in reader:
        y.append(float(line[0]))
        X.append(line[1:])  # 這里要將數(shù)據(jù)轉(zhuǎn)化成float類型

        cur_line_num += 1
        if cur_line_num >= minibatch_size:
            X, y = np.array(X), np.array(y)  # 將數(shù)據(jù)轉(zhuǎn)成numpy的array類型并返回
            yield X, y#就跟return一樣,唯一的區(qū)別就是,yield會(huì)停止在這里
            X, y = [], []
            cur_line_num = 0
    csvfile.close()

# 生成測(cè)試文件
minibatch_test_iterators = iter_minibatches(test_file, minibatch_size=5000)
X_test, y_test = minibatch_test_iterators.next()  # 得到一份測(cè)試文件
2. 增量訓(xùn)練
from sklearn.linear_model import SGDClassifier
sgd_clf = SGDClassifier()  # SGDClassifier的參數(shù)設(shè)置可以參考sklearn官網(wǎng)
minibatch_train_iterators = iter_minibatches(data_part_file, minibatch_size=2000)

for i, (X_train, y_train) in enumerate(minibatch_train_iterators):
    # 使用 partial_fit ,并在第一次調(diào)用 partial_fit 的時(shí)候指定 classes
    sgd_clf.partial_fit(X_train, y_train, classes=np.array([0, 1]))
    print("{} time".format(i))  # 當(dāng)前次數(shù)
    print("{} score".format(sgd_clf.score(X_test, y_test)))  # 在測(cè)試集上看效果
3. 結(jié)果
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. 一點(diǎn)補(bǔ)充
  1. 當(dāng)SGD的損失函數(shù)為log時(shí),SGD等價(jià)于LR。
  2. 數(shù)據(jù)只迭代一次分類器可能還沒完全收斂,可以多迭代幾次
  3. mini-batch的量不要設(shè)置太小,太小的話,需要多迭代幾次才能收斂
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容