ロード・トゥ・ザ・ホワイトハッカー

ホワイトハッカーはじめました

フィッシングデータの機械学習

フィッシングデータの機械学習

以前、フィッシングサイトのデータセットを調べた。

chikuwamarux.hatenablog.com

 

これを使って、機械学習をしてみる。

 

この書籍を参考にさせてもらう。

www.oreilly.co.jp

 

サンプルコードは以下にある。

github.com

 

サンプルコードでは、ロジステック回帰のアルゴリズムを利用して、ハイパーパラメーターを検索して、その後、決定木のアルゴリズムを使っている。

 

ロジステック回帰では、92%程度の精度が出て、決定木では95%ほどになる。

別のアルゴリズムである、ランダムフォレストを試してみる。

 

ランダムフォレストによる機械学習

サンプルコードの一部を変更した。元のデータをdata.xlsxに格納して、データ格納先をnumpy配列からDataFrameに変更して、RandomForestClassifierでの機械学習

コードは以下の通り。

 

#データロード
import pandas as pd
training_data = pd.read_excel('data.xlsx')


# Xに特徴量30個を格納、yにフィッシングサイトか、どうかResultを格納
X = training_data.iloc[:,0:30]
y = training_data.iloc[:,30]


#訓練用データを8割、検証用データを2割
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=True, random_state=101)


from sklearn.ensemble import RandomForestClassifier
# ランダムフォレスト 学習モデルを作成(他のアルゴリズムはここが変わる)
model = RandomForestClassifier()


# 訓練用データを使って検出器を訓練する。
model.fit(X_train, y_train)
 
# 予測させる。
predictions = model.predict(X_test)


# このフィッシング検出器の正解率を出力させる。
from sklearn.metrics import accuracy_score 
accuracy = 100.0 * accuracy_score(y_test, predictions)
print("精度: {}".format(accuracy))
 

これで、96%以上の精度が出る。やはり正確性という点では、ランダムフォレストに軍配が上がる。

ただ、ハイパーパラメーターを検索して、適用しても精度が下がる。

 

ランダムフォレストのハイパーパラメーターは以下。

scikit-learn.org

 

よく使用されるのは、以下の2つ。

  • n_estimators=Treeの数
  • max_depth=深さ

デフォルトでは、

  • n_estimators=100
  • max_depth=none

となっている。

 

ハイパーパラメーターを探索すると、

  • n_estimators=900くらい
  • max_depth=21くらい

となる。

これを適用すると、デフォルトパラメーターよりも精度が下がるので、過学習しているのかもしれない。

 

ランダムフォレストの利点としては、重要な特徴量が分かること。つまり、どの特徴量が結果に影響を与えているのか、が分かる。

コードは以下の通り。

import numpy as np
import matplotlib.pyplot as plt

# Feature Importanceの抽出
feature = model.feature_importances_   

#特徴量の名前
label = training_data.columns[0:]

#特徴量の重要度順(降順)
indices = np.argsort(feature)[::-1]

for i in range(len(feature)):
    print(str(i + 1) + "   " + str(label[indices[i]]) + "   " + str(feature[indices[i]]))


#グラフ表示
plt.title('Feature Importance')
plt.bar(range(len(feature)),feature[indices], color='lightblue', align='center')
plt.xticks(range(len(feature)), label[indices], rotation=90)
plt.xlim([-1len(feature)])
plt.tight_layout()
plt.show()

上記コードにより、下記グラフが得られる。

 

以下2つの項目で半分以上の重要度を占めている。
SSLfinal_State : 0.331481451216863
URL_of_Anchor : 0.24362546519501826

 

SSLfinal_Stateは、サーバー証明書の状態。が信頼できるもので、有効期限が1年以上のもの、自己証明書、それ以外、という区分け。

URL_of_Anchorは、ページ内のリンクがリンク先が無いものの割合。31%未満、31%~67%、それ以外という区分け。

 

ランダムフォレストは、上記2つを重視して判定していることが分かるので、人間も同様にそこを重点的に見るとフィッシングと判定できる精度が上がる。