はじめに
この実験では、異なる種類の特徴を含むデータセットに対して Scikit-Learn の「ColumnTransformer」をどのように使用するかを学びます。この手法は、データセットに異なる特徴抽出と処理パイプラインが必要なコンポーネントが含まれている場合に役立ちます。
VM のヒント
VM の起動が完了したら、左上隅をクリックしてノートブックタブに切り替え、Jupyter Notebook を使って練習しましょう。
時々、Jupyter Notebook が読み込み終了するまで数秒待つ必要がある場合があります。Jupyter Notebook の制限により、操作の検証を自動化することはできません。
学習中に問題に遭遇した場合は、Labby にお問い合わせください。セッション後にフィードバックを提供してください。そうすれば、迅速に問題を解決します。
データセット
20 のトピックに関するニュースグループの投稿から構成される 20 ニュースグループデータセットを使用します。このデータセットは、特定の日付の前後に投稿されたメッセージに基づいて学習用とテスト用のサブセットに分割されます。実行時間を短縮するため、2 つのカテゴリの投稿のみを使用します。
categories = ["sci.med", "sci.space"]
X_train, y_train = fetch_20newsgroups(
random_state=1,
subset="train",
categories=categories,
remove=("footers", "quotes"),
return_X_y=True,
)
X_test, y_test = fetch_20newsgroups(
random_state=1,
subset="test",
categories=categories,
remove=("footers", "quotes"),
return_X_y=True,
)
トランスフォーマーの作成
データセットから特徴を抽出するトランスフォーマーを作成します。データ変換を行う 2 つの関数を定義し、その後 Scikit-Learn の「FunctionTransformer」を使ってトランスフォーマーを作成します。
def subject_body_extractor(posts):
## construct object dtype array with two columns
## first column = 'subject' and second column = 'body'
features = np.empty(shape=(len(posts), 2), dtype=object)
for i, text in enumerate(posts):
## temporary variable `_` stores '\n\n'
headers, _, body = text.partition("\n\n")
## store body text in second column
features[i, 1] = body
prefix = "Subject:"
sub = ""
## save text after 'Subject:' in first column
for line in headers.split("\n"):
if line.startswith(prefix):
sub = line[len(prefix) :]
break
features[i, 0] = sub
return features
subject_body_transformer = FunctionTransformer(subject_body_extractor)
def text_stats(posts):
return [{"length": len(text), "num_sentences": text.count(".")} for text in posts]
text_stats_transformer = FunctionTransformer(text_stats)
分類パイプライン
データセットから特徴を抽出し、それらを結合し、結合された特徴セットで分類器を学習するパイプラインを作成します。これを達成するために、Scikit-Learn の「Pipeline」と「ColumnTransformer」を使用します。
pipeline = Pipeline(
[
## Extract subject & body
("subjectbody", subject_body_transformer),
## Use ColumnTransformer to combine the subject and body features
(
"union",
ColumnTransformer(
[
## bag-of-words for subject (col 0)
("subject", TfidfVectorizer(min_df=50), 0),
## bag-of-words with decomposition for body (col 1)
(
"body_bow",
Pipeline(
[
("tfidf", TfidfVectorizer()),
("best", TruncatedSVD(n_components=50)),
]
),
1,
),
## Pipeline for pulling text stats from post's body
(
"body_stats",
Pipeline(
[
(
"stats",
text_stats_transformer,
), ## returns a list of dicts
(
"vect",
DictVectorizer(),
), ## list of dicts -> feature matrix
]
),
1,
),
],
## weight above ColumnTransformer features
transformer_weights={
"subject": 0.8,
"body_bow": 0.5,
"body_stats": 1.0,
},
),
),
## Use a SVC classifier on the combined features
("svc", LinearSVC(dual=False)),
],
verbose=True,
)
学習とテスト
学習用データに対してパイプラインを適合させ、X_testのトピックを予測するために使用します。その後、パイプラインの性能指標を表示します。
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)
print("Classification report:\n\n{}".format(classification_report(y_test, y_pred)))
まとめ
この実験では、異なる種類の特徴を含むデータセットに対して Scikit-Learn の「ColumnTransformer」をどのように使用するかを学びました。データセットから特徴を抽出するトランスフォーマーを作成し、それらを使って結合された特徴セットで分類器を学習させました。「ColumnTransformer」により、単一のパイプラインで異なる種類の特徴を処理することができました。