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

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

ただいまの
回答率

90.43%

  • Python

    9774questions

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

  • Python 3.x

    7909questions

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

  • Python 2.7

    1363questions

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

  • 機械学習

    799questions

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

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

受付中

回答 4

投稿

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

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/23 22:17 編集

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

    LightGBMの解説動画か何かをみていたときに
    精度に寄与しないデータもたくさん入っていたけど
    下がりはしなかったというのを聞いたことがあったので
    決定木モデルはそのあたりが安心なのですね。

    分岐が多いほど機械側は嬉しいというのも
    お聞きして良かったです!

    1つ気になっていたのが
    例えば特徴量Aと特徴量Bがあったとき
    それらを掛け合わせた特徴量Cを追加する場合
    A=0.1 B=0.5 のとき C=0.1×0.5=0.05
    A=0.5 B=0.1 のとき C=0.5×0.1=0.05
    となり
    どちらもC=0.05となるので
    これだとあまり意味がない選択肢が増えて逆に迷うんじゃ・・・
    と思っていました。

    このケースだとCは単純に
    重要ではないと判断されて捨てられるか、

    内部的にAとCの組み合わせやBとCの組み合わせが
    試されるということになる
    といった理解でいいのでしょうか?

    キャンセル

  • 2018/12/23 23:31 編集

    そうですね、内部的にAとC、BとCなどの組み合わせは試されるでしょうから
    そのように機械が試した上で、重要でなければモデルに貢献しない特徴量になると思います!

    ちなみにこの単純なテクニックは昔私がやったときは本当に少ししか精度が上がらなかったです。
    一応その中でも特徴量重要度の上位の者同士だと効果は高めだったと思います。。汗

    キャンセル

  • 2018/12/24 00:22

    maro_amoebaさんが以前試された時は
    少ししか上がらなかったのですね・・・。

    内部的にはやはりAとCやBとCも試されている感じなんですね。

    ランダムフォレストの概要を見ていると、
    最初のノードでAが選ばれ次のノードでBが選ばれる
    というように、
    「Aが選ばれて分けられた後、分けられたデータに対してBで判定される」(ランダムなので1つの例)
    という理解でいます。

    ただこれは、
    Aがこうなって、かつBがこうなっている
    という判断を「1つのノードで」行われていない気がしてですね。

    少ししか精度が上がらなかったということは、
    明示的に掛け合わせなくても
    内部的にA×Bが実行されている
    と見ていいんでしょうか・・・

    Aで分けられて次のノードへ進み⇒分けられたデータに対してBで分けられる
    というのと
    AとBを考慮して分けられて⇒次のノードへと進む
    のとでは
    違うような気がしていて混乱しています^^;

    キャンセル

  • 2018/12/24 10:23 編集

    決定木では説明変数の組み合わせは、内部はそれぞれのかけ算をしているわけではないかと思います。(LightGBMはそれすらもしてるかもしれないですが私はわからないです)
    こちらの木構造の可視化の部分を見ると、「組み合わせ」という意味が伝わるかもしれないです。
    http://www.randpy.tokyo/entry/python_random_forest

    また、決定木、ランダムフォレスト、勾配ブースティング(LightGBMなど)が区別がついていないようですので、
    時間のあるときに勉強するといいかもです。

    参考に:決定木についての説明を丁寧にしてくれている動画があります(他の手法も解説してくれています)
    https://www.youtube.com/watch?v=irTbuevXauk&t=1214s

    キャンセル

  • 2018/12/24 12:28

    AとBといった特徴量があった場合、C = A × B といった
    新たな特徴を定義しなくても、例えば A > 10 で分岐し B > 5で分岐することで C で表現できる情報の一部を表現できますが、それはC > 50 で捉えられる情報の一部でしかない、という話ですかね。そのため、掛け合わせることで、それなしではできなかった分け方ができる可能性はあると思います。

    キャンセル

  • 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 21:55

    おおおおおおおお!
    DecisionTreeで見ると確かに違いが出ていますね~。

    書いていただいたコードをRandomForestClassifierに変えると
    同じになりましたが、
    木1個単位では少ない枝分かれでより早く精度を上げている
    感じになるのですね。

    ご丁寧にコードまで書いてくださってありがとうございます^^

    キャンセル

  • 2018/12/23 22:18 編集

    すいませんランダムフォレストで試してなかったんですが、確かにデフォルトパラメータのままだとクロスバリデーションスコアの差がほとんどなくなりますね。ただ、n_estimators=500にして、クロスバリデーションすると、1.2%ほど掛け合わせ特徴量を使った方が正解率が高くなりますね。

    自分も勉強になりました!

    キャンセル

  • 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.43%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

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

  • Python

    9774questions

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

  • Python 3.x

    7909questions

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

  • Python 2.7

    1363questions

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

  • 機械学習

    799questions

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