Pythonのsvmで以下のcodeを使用します。
from sklearn import datasets
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
iris = datasets.load_iris()
X, y = iris.data, iris.target
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))
clf.fit(X, y)
proba = clf.predict_proba(X)
しかし、それには膨大な時間がかかります。
実際のデータディメンション:
train-set (1422392,29)
test-set (233081,29)
どうすれば高速化できますか(並列または他の方法)?助けてください。私はすでにPCAとダウンサンプリングを試しました。
6つのクラスがあります。編集:発見 http://scikit-learn.org/stable/modules/generated/sklearn.linear_model.SGDClassifier.html しかし、私は確率推定を望んでおり、svmにはそうではないようです。
編集:
from sklearn import datasets
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC,LinearSVC
from sklearn.linear_model import SGDClassifier
import joblib
import numpy as np
from sklearn import grid_search
import multiprocessing
import numpy as np
import math
def new_func(a): #converts array(x) elements to (1/(1 + e(-x)))
a=1/(1 + math.exp(-a))
return a
if __== '__main__':
iris = datasets.load_iris()
cores=multiprocessing.cpu_count()-2
X, y = iris.data, iris.target #loading dataset
C_range = 10.0 ** np.arange(-4, 4); #c value range
param_grid = dict(estimator__C=C_range.tolist())
svr = OneVsRestClassifier(LinearSVC(class_weight='auto'),n_jobs=cores) ################LinearSVC Code faster
#svr = OneVsRestClassifier(SVC(kernel='linear', probability=True, ##################SVC code slow
# class_weight='auto'),n_jobs=cores)
clf = grid_search.GridSearchCV(svr, param_grid,n_jobs=cores,verbose=2) #grid search
clf.fit(X, y) #training svm model
decisions=clf.decision_function(X) #outputs decision functions
#prob=clf.predict_proba(X) #only for SVC outputs probablilites
print decisions[:5,:]
vecfunc = np.vectorize(new_func)
prob=vecfunc(decisions) #converts deicision to (1/(1 + e(-x)))
print prob[:5,:]
編集2:user3914041による回答では、非常に低い確率推定が得られます。
可能な限りSVCに固執し、完全なデータセットでトレーニングする場合は、データのサブセットでトレーニングされたSVCのアンサンブルを使用して、分類子ごとのレコード数を減らすことができます(明らかに複雑性に2次的な影響があります)。 ScikitはBaggingClassifier
ラッパーでそれをサポートしています。これにより、単一の分類器と比較して(改善されていないとしても)同様の精度が得られ、トレーニング時間が大幅に短縮されます。個々の分類子のトレーニングは、n_jobs
パラメーターを使用して並行して実行するように設定することもできます。
あるいは、ランダムフォレスト分類器の使用も検討します。これは、マルチクラス分類をネイティブにサポートし、高速で、min_samples_leaf
が適切に設定されている場合にかなり良い確率推定値を提供します。
私は、10個のSVCのアンサンブルを使用して100回爆破された虹彩データセットで簡単なテストを行い、それぞれがデータの10%でトレーニングを行いました。単一の分類子よりも10倍以上高速です。これらは私のラップトップで得た数字です:
単一のSVC:45秒
アンサンブルSVC:3秒
ランダムフォレスト分類子:0.5秒
数値の生成に使用したコードを以下に示します。
import time
import numpy as np
from sklearn.ensemble import BaggingClassifier, RandomForestClassifier
from sklearn import datasets
from sklearn.multiclass import OneVsRestClassifier
from sklearn.svm import SVC
iris = datasets.load_iris()
X, y = iris.data, iris.target
X = np.repeat(X, 100, axis=0)
y = np.repeat(y, 100, axis=0)
start = time.time()
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))
clf.fit(X, y)
end = time.time()
print "Single SVC", end - start, clf.score(X,y)
proba = clf.predict_proba(X)
n_estimators = 10
start = time.time()
clf = OneVsRestClassifier(BaggingClassifier(SVC(kernel='linear', probability=True, class_weight='auto'), max_samples=1.0 / n_estimators, n_estimators=n_estimators))
clf.fit(X, y)
end = time.time()
print "Bagging SVC", end - start, clf.score(X,y)
proba = clf.predict_proba(X)
start = time.time()
clf = RandomForestClassifier(min_samples_leaf=20)
clf.fit(X, y)
end = time.time()
print "Random Forest", end - start, clf.score(X,y)
proba = clf.predict_proba(X)
各レコードがBaggingClassifier
のトレーニングに1回だけ使用されるようにする場合は、bootstrap
パラメーターをFalseに設定できます。
SVM分類器はそれほど簡単に拡張できません。ドキュメントから、sklearn.svm.SVC
の複雑さについて。
適合時間の複雑さは、サンプル数の2次以上であり、10000サンプル以上のデータセットへのスケーリングが困難です。
Scikit-learnには、svm.linearSVC
があります。どうやらそれはあなたのデータを処理することができる可能性があります。
または、別の分類器を使用することもできます。確率推定が必要な場合は、ロジスティック回帰をお勧めします。ロジスティック回帰には、「適切な」確率を出力するために 確率較正 を必要としないという利点もあります。
編集:
linearSVC
の複雑さについて知りませんでしたが、最終的に ユーザーガイド で情報を見つけました。
また、線形の場合、liblinear実装によってLinearSVCで使用されるアルゴリズムは、libsvmベースのSVCカウンターパートよりもはるかに効率的であり、数百万のサンプルや機能にほぼ線形にスケーリングできることに注意してください。
linearSVC
から確率を取得するには、 このリンク をチェックアウトします。上記でリンクした確率較正ガイドから数リンク離れているだけで、確率を推定する方法が含まれています。すなわち:
prob_pos = clf.decision_function(X_test)
prob_pos = (prob_pos - prob_pos.min()) / (prob_pos.max() - prob_pos.min())
リンクに示されているように、推定値はおそらくキャリブレーションなしでは不十分です。
トップアンサーで簡単に言及されました。コードは次のとおりです。これを行う最も簡単な方法は、 n_jobs
パラメータ :行を置き換えることです。
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'))
と
clf = OneVsRestClassifier(SVC(kernel='linear', probability=True, class_weight='auto'), n_jobs=-1)
これにより、以前と同じ計算を実行しながら、コンピューターで使用可能なすべてのCPUが使用されます。
_kernel_approximation
module SVMをこのような多数のサンプルにスケールアップします。
class_weight == 'auto'
を使用して言及されたいくつかの回答。 0.17以降のsklearnバージョンの場合は、代わりにclass_weight == 'balanced'
を使用してください。 https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html