Scikit-LearnのFeatureUnion関数が初見で結構わかりにくかったのでメモしておきます。「Marking imputed values」を見ていて?となり、学習しました。
これは特徴量エンジニアリング時に特徴量を一括処理をしてまとめてくれます。Pipleline
モジュールに含まれており、有名なPipeline
関数の兄弟みたいなものです。
FeatureUnionの簡易版でmaike_union
関数があります。使うときは、どちらがいいか検討すべきですね。
シンプルな使い方
irisデータを読み込み、1列目の「sepal length (cm)」だけをDataframeに設定します。DataFrame化せずにNumpy配列のままでもOKですが、単純に私がNumpy慣れしていないので入れているだけです。
import pandas as pd
from sklearn import datasets
from sklearn.pipeline import FeatureUnion
from sklearn.preprocessing import FunctionTransformer
# Iris データセットを読み込み、1列目だけをDataFrameへ設定
iris = datasets.load_iris()
df = pd.DataFrame(iris.data[:, 0], columns=[iris.feature_names[0]])
print(df.head())
sepal length (cm)
0 5.1
1 4.9
2 4.7
3 4.6
4 5.0
FunctionTransformer
関数使って以下の2種類の特徴量に変換しています。通常、変換をするので「変換」という言葉を使っていますが、今回の例では「1. raw」は単純にするために変換すらしていません。
- raw: ただ元の値を出すだけ
- double: 元の値を2倍
# 複数の特徴量を結合する
union = FeatureUnion([('1.raw', FunctionTransformer(lambda x: x)),
('2.double', FunctionTransformer(lambda x: x*2))])
print(union.fit_transform(df)[:5])
結果セットを見るともとの値と2倍になった値が出ていますね。
[[ 5.1 10.2]
[ 4.9 9.8]
[ 4.7 9.4]
[ 4.6 9.2]
[ 5. 10. ]]
以下の記事を見る限り、結果はDataFrameにはならないようです。Numpyに慣れていない私のような人間には使いにくい。
実際の使い方
「シンプルな使い方」では、使い方に焦点を当てたので実際にどんな使い方をするかです。
mnistの手書き数字データを引っ張ってきます。
from sklearn.datasets import load_digits
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.naive_bayes import GaussianNB
from sklearn.pipeline import Pipeline, FeatureUnion
from sklearn.model_selection import cross_validate
import pprint
digits = load_digits()
print(digits.data.shape)
1797レコードの8×8の手書きデータがあります。
(1797, 64)
PCAとLDAで特徴量削減をして、Gaussianナイーブベイズで分類します。このときにPCAとLDAで同時並列で特徴量を生成し、結合します。今回は使っていませんがFeatureUnion
にはn_jobs
というパラメータがあり、並列処理が可能です。
pca = PCA(n_components=30)
lda = LDA()
gnb = GaussianNB()
pca_lda_gnb = Pipeline([("reduction", FeatureUnion([("pca", pca),
("lda", lda)])),
("gnb", gnb)])
pprint.pprint(cross_validate(pca_lda_gnb, digits.data, digits.target, cv=3))
で、結果は以下のようなscoreと時間が出ます。
{'fit_time': array([0.21725082, 0.16855884, 0.08645368]),
'score_time': array([0.01812887, 0.00961113, 0.00560999]),
'test_score': array([0.92821369, 0.93489149, 0.92153589])}
参考
以下の記事を参考にしました。