久しぶりにLibSVMLoaderをアップデートした。
$ gem install libsvmloader
これまでNMatrixで特徴ベクトルとラベルを表現していたが、これをRubyのArrayに変えた。Arrayにすることで、NMatrixだけでなくNumo::NArrayでも使用できる。
require 'libsvmloader' require 'nmatrix/nmatrix' # LIBSVM形式のファイルを読み込む。 samples, labels = LibSVMLoader.load_libsvm_file('foo.t') # ArrayをもとにNMatrixによるサンプル行列・ラベルベクトルを生成する。 samples_nm = N[*samples] labels_nm = N[*labels]
require 'libsvmloader' require 'numo/narray' # LIBSVM形式のファイルを読み込む。 samples, labels = LibSVMLoader.load_libsvm_file('foo.t') # ArrayをもとにNumo::NArrayによるサンプル行列・ラベルベクトルを生成する。 samples_na = Numo::NArray[*samples] labels_na = Numo::NArray[*labels]
また、liblinear-rubyは、RubyのArrayでデータをやりとりするので、より使いやすくなる。
$ gem install liblinear-ruby
$ wget https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/multiclass/pendigits $ wget https://www.csie.ntu.edu.tw/~cjlin/libsvmtools/datasets/multiclass/pendigits.t
訓練は次のようになる。
require 'libsvmloader' require 'liblinear' # pendigitsの訓練データセットを読み込む。 samples, labels = LibSVMLoader.load_libsvm_file('pendigits') # Liblinearで線形サポートベクターマシンを学習する。 Liblinear.quiet_mode model = Liblinear.train( { solver_type: Liblinear::L2R_L2LOSS_SVC }, labels, samples ) # 学習したモデルを保存する。 model.save('pendigits.model')
そしてテストは次のようになる。
require 'libsvmloader' require 'liblinear' # pendigitsのテストデータセットを読み込む。 samples, labels = LibSVMLoader.load_libsvm_file('pendigits.t') # 学習したモデルを読み込む。 model = Liblinear::Model.load('pendigits.model') # テストデータのラベルを推定する(predictメソッドにはサンプルを1つずつ渡す)。 predicted = samples.map { |s| Liblinear.predict(model, s).to_i } # 正解ラベル数をカウントする。 n_samples = labels.size n_corrects = Array.new(n_samples) { |n| labels[n] == predicted[n] ? 1 : 0 }.count(1) # 分類の正確度を出力する。 puts "Accuracy: %.4f" % (n_corrects.fdiv(n_samples))
これらのスクリプトを実行すると、正確度が出力される。約9割が正解している。
Accuracy: 0.8788
だいたい以上のような感じ。インターフェースはあまり変えなかった。label_dtypeやvalue_dtypeオプションを使用すると、ラベルや特徴ベクトルの型を指定できる。また、LIBSVM形式では、特徴ベクトルの添字が1から始まるが、zero_basedオプションにtrueを渡せば、0から始まるとして読み込みを行う。詳しくはドキュメントで。
https://www.rubydoc.info/gems/libsvmloader/0.2.0/LibSVMLoader