質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.38%

  • Python

    12856questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Python 3.x

    10730questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Python 2.7

    1487questions

    Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

  • 機械学習

    1017questions

    機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

特徴量を掛け合わせることの有効性について

受付中

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 673

kururi10

score 19

機械学習の木系モデルを使う際の話なのですが、
特徴量の積は有効なのかあまり意味がないのか
お聞きしたくて投稿しました。

例えば特徴量がA,B,Cと3つあるとして、
これらは全てカテゴリ変数ではないものとします。
そして、モデルは木系のモデルを使うとします。

その際、
A×B=D
A×C=E
B×C=F
という風にA,B,Cの特徴量を掛け合わせた
新しい特徴量D,E,Fを作って追加して学習させることは
有効なのか、あまり意味がないことなのか
どちらなのでしょうか?

自分はまだあまり詳しくわかっていなくて
間違っているかもしれませんが、
例えば木系のモデルとしてランダムフォレストを使う場合
根っこからたどって
1つ目のノードで特徴量Aが選ばれ、2つ目のノードで特徴量Bが選ばれたとすると
イメージ的にAかつBのように判断されているのではないかと思い
それは新たにA×B=Dという特徴量を追加しなくても
ちゃんと考慮されてるんじゃないかなと
なんとなく思っていますが・・・。

試しに特徴量同士の積を新たな特徴量として
実際にやってみたらいいのですが、
今やっている問題は特徴量の数が5000ぐらいあるので
そもそも意味があるものなのか
一般論としてお聞きしたいなと思いました。

ご回答のほど宜しくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

シンプルに、決定木モデルは分岐点の候補が多ければ多いほど機械側は嬉しいです。  
使える特徴量かどうかは機械側が判断します。  

仮に決定木モデルはゴミを投げても、特徴量の重要度を下げ使わない判断をしてくれますのでその点は安心です。
そのため特徴量を掛け合わせたり、足したりといったこともテクニックとしてありますし、多少有効に働くことが多いです。  

もちろんGolden Feature(問題空間をよく表す最適な特徴)を与えるのが理想です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/24 14:46

    >maro_amoebaさん

    うーん、
    僕が上記のコメントで
    「最初のノードでAが選ばれ次のノードでBが選ばれる」
    と言ったのは、
    教えていただいたページの
    木構造の可視化の部分のノードのお話のことです。

    教えていただいたページの例で言うと、
    最初のノードでSexが選ばれ次のノードでPclassが左側に分岐されたものでは選ばれている
    という構造になっていますよね。

    これは最初のノードでSexで情報利得が最大となって分割がされ、
    次の左側ノードでPclassで情報利得が最大となって分割がされていますが

    これは1つのノードでSexとPclassの両方を考慮した分け方になっていない
    というのが上記のコメントで僕が言いたかったことです。


    Sexがこの値でPclassがこの値の時に情報利得が最大となったので
    Sex>=○ かつ Pclass>=○ で分割しましょう
    という形になっていない。

    にもかかわらず、
    特徴量A×特徴量Bを計算した特徴量を追加しても
    maro_amoebaさんの時は少ししか精度が上がらなかったのは
    なぜだろうと・・・。

    仮に
    Sex>=○ かつ Pclass>=○ で分割しましょう
    という形になっているんだったら、
    特徴量A×特徴量Bの特徴量を追加しても
    精度が少ししか上がらないのは分かるんですけどね。

    純粋に、それはなぜなんだろうと。
    内部的に特徴量A×特徴量Bの効果があるんかなと・・・。

    全体で見ると確かに組み合わせではあるんですが、
    分割の判断の際に組み合わせは考慮されていない
    という構造なんですよね。。。

    キャンセル

  • 2018/12/24 14:55

    >noukenさん

    C > 50 で捉えられる情報の一部でしかない
    というのの一部というのが
    どこなのかちょっとまだ良くわからないのですが、

    X軸がAでY軸がBの平面を考えると
    A > 10 で分岐し B > 5
    なら
    C > 50の領域となり
    同じなような気もするし・・・。

    A > 10 で分岐したときに、A <= 10は捨てられずに
    もうひとつの分岐に残ると考えると
    A > 10 で分岐し B > 5
    の方がむしろ多くの情報が捉えられている気もするし。。。

    うむう、難しい^^;

    1個上のmaro_amoebaさんへのお返事でも書いた、
    分割の判断の際に組み合わせは考慮されていない
    という所を考えてみると
    C > 50が有効とも捉えられますしね。
    (Cが組み合わせたものなので、それを分岐の判断の際に使っている)

    どうなんでしょうね・・・。

    キャンセル

  • 2018/12/24 15:00 編集

    >noukenさん

    あ、平面上の話は違ったかもです。

    A > 10 で分岐し B > 5で
    C > 50のとき
    平面上の話は無関係ですね。

    失礼しました^^;

    キャンセル

0

randomforestにそのまま突っ込むよりも、明示的に掛け合わせた方がモデルにとって学習しやすいといったケースもあると思います。自分の経験上、やってみないとわかりませんが、効くこともあるといった感じでう。5000を全て掛けあわせるのは厳しいものがあると思うので、特徴量重要度上位の者同士であったり、ドメイン知識から考えて有効ではないかと考えられる組み合わせなどを試してみるのはどうでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/23 02:06

    noukenさん、ご回答いただきありがとうございます!

    なるほど、重要度が高いもの同士を掛け合わせるなどで
    効率化してみるといいのではないかということなんですね。

    モデルにとって学習しやすいというのは、
    特に特徴的だった値同士が掛け合わせることによって
    さらに強力に色濃く特徴として出てくるので
    それをモデルが見分けやすくなる
    というイメージでしょうか?

    キャンセル

  • 2018/12/23 11:01

    そのようなイメージで良いと思います。僕もそれほど専門的なことはわからないですが、モデルに「察して」もらうよりもこちらが「’示して」あげた方が分類しやすくなることもあるのかなぁというイメージです。

    キャンセル

  • 2018/12/23 21:49

    なるほど、なるほど。
    察してもらうより、しっかりと示してあげたほうがいい
    というのは分かりやすい表現ですね^^

    キャンセル

0

ちょっと気になったのでbreast_cancerのデータセットで実際にやってみました。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# モデルの木構造の視覚化に必要なパッケージ
from sklearn import tree
import pydotplus as pdp

breast_cancer = load_breast_cancer()
df = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)

df['target'] = breast_cancer.target
#一応シャッフル
df = df.sample(frac=1, random_state=1)
target = df['target']
df.drop('target', axis=1, inplace=True)

x_train, x_val, y_train, y_val = train_test_split(df, target, test_size=0.25, random_state=1)
x_train.shape, x_val.shape, y_train.shape, y_val.shape

model = DecisionTreeClassifier(random_state=1)
model.fit(x_train, y_train)
y_pred = model.predict(x_val)
print('acc: {}'.format(accuracy_score(y_val, y_pred)))

importance_df = pd.DataFrame()
importance_df['feature'] = breast_cancer.feature_names
importance_df['importance'] = model.feature_importances_
importance_df = importance_df.sort_values(by='importance', ascending=False).head(10)
sns.barplot(x='importance', y='feature', data=importance_df)

#file_name = "./tree_visualization.png"
#dot_data = tree.export_graphviz(model, out_file=None, filled=True, rounded=True, feature_names=df.columns, 
                                #class_names=breast_cancer.target_names, special_characters=True)
#graph = pdp.graph_from_dot_data(dot_data)
#graph.write_png(file_name)

acc: 0.9370629370629371

np.mean(cross_val_score(DecisionTreeClassifier(random_state=1), df, target, cv=5))

0.93674490188534043

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# モデルの木構造の視覚化に必要なパッケージ
from sklearn import tree
import pydotplus as pdp
import itertools

breast_cancer = load_breast_cancer()
df = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)

df['target'] = breast_cancer.target
#一応シャッフル
df = df.sample(frac=1, random_state=1)
target = df['target']
df.drop('target', axis=1, inplace=True)

#特徴量の掛け合わせ
for f1, f2 in itertools.combinations(df.columns, 2):
    df[f1+'*'+f2] = df[f1] * df[f2]

x_train, x_val, y_train, y_val = train_test_split(df, target, test_size=0.25, random_state=1)
x_train.shape, x_val.shape, y_train.shape, y_val.shape

model = DecisionTreeClassifier(random_state=1)
model.fit(x_train, y_train)
y_pred = model.predict(x_val)
print('acc: {}'.format(accuracy_score(y_val, y_pred)))

importance_df = pd.DataFrame()
importance_df['feature'] = df.columns
importance_df['importance'] = model.feature_importances_
importance_df = importance_df.sort_values(by='importance', ascending=False).head(10)
sns.barplot(x='importance', y='feature', data=importance_df)

#file_name = "./tree_visualization.png"
#dot_data = tree.export_graphviz(model, out_file=None, filled=True, rounded=True, feature_names=df.columns, 
                                #class_names=breast_cancer.target_names, special_characters=True)
#graph = pdp.graph_from_dot_data(dot_data)
#graph.write_png(file_name)

acc: 0.965034965034965

np.mean(cross_val_score(DecisionTreeClassifier(random_state=1), df, target, cv=5))

0.95087341285109661

決定木の可視化にはgraphvizのinstallが必要ですが、それを見ると掛け合わせ特徴を用いた方が少ない枝分かれでより高い正解率を達成しています。もちろんデータにもよりますが、試してみる価値はあると思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/23 22:38

    おお、ランダムフォレストでも差が出ましたか!
    試していただいてありがとうございます^^

    ちなみにnoukenさんはランダムフォレストの計算式のような
    数学的な部分も理解を進めながら使用されていますか?
    僕は数学的な部分はさっぱりなもので・・・^^;

    キャンセル

  • 2018/12/23 23:38

    機械学習の勉強始めた頃は難しいところは飛ばしてとりあえず使えたらいいか、っていう感じでしたが、勉強を進めるにつれやはり理論もある程度わかっていた方がいいと気づいたので、最近は理解しようと努力はしています。でもなかなか難しいですよね。。。

    キャンセル

  • 2018/12/24 00:11

    そうですよね・・・内部的にどんな動作をしているか
    ある程度分かっておいたほうがいいですよね・・・。
    僕は株価の分析に機械学習を使っているのですが、
    手法のどこを特徴量にすればいいかに頭を使っていて
    なかなか理論的なことが進められていないので
    勉強していこうと思います。。。
    難しい部分も多いですよね^^;

    キャンセル

0

データ依存ですが、効くときは効きます。

たとえば底辺と高さがわかっている長方形の面積がしきい値を超えるかどうか、というタスクを考えます。

import numpy as np
from sklearn.tree import DecisionTreeClassifier as DTC, export_graphviz

xy = np.random.rand(300, 2)*10
label = (xy[:,0] * xy[:,1] > 20).astype(int)

dtc = DTC()
dtc.fit(xy, label)
export_graphviz(dtc, "tree1.dot")

xy2 = np.hstack([xy, (xy[:,0]*xy[:,1]).reshape(-1, 1)])
dtc = DTC()
dtc.fit(xy2, label)
export_graphviz(dtc, "tree2.dot")

"""
$ dot -Tpng tree1.dot -o tree1.png
$ dot -Tpng tree2.dot -o tree2.png
"""

tree1.png
イメージ説明

tree2.png
イメージ説明

実データでここまで顕著なのはないと思いますが、少しでもこういう傾向を持っていれば効きます。掛け合わせ変数がより効果的な説明変数であれば木を浅くでき、汎化性能に影響することでしょう。

参考:
[入門]初心者の初心者による初心者のための決定木分析 - Qiita

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/25 22:03 編集

    hayataka2049さん、ご回答いただきありがとうございます!

    なるほど、シンプルな事例を挙げていただき
    確かに浅い深さでもうまく判別できていますね!

    下のmaro_amoebaさんとnoukenさんとのやり取りの中書いた、

    決定木は
    「分割の判断の際に特徴量の組み合わせは考慮されていない」
    ように見えることについてなのですが、

    これが考慮されていないから、あえて掛け合わせることに意味が出てくる場合がある

    と考えてもよろしいのでしょうか?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.38%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Python

    12856questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Python 3.x

    10730questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Python 2.7

    1487questions

    Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

  • 機械学習

    1017questions

    機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。