機械学習の基礎:「分類アルゴリズム (6) - 決定木」

1. デシジョンツリー

1. 決定木を理解する.
決定木の考え方の起源は非常に単純です. プログラミングにおける条件分岐構造は if-else 構造です. 最も初期の決定木はこのタイプの構造を使用してセグメント化する分類学習手法ですデータ。

2. 会話例

なぜこの女の子が年齢を判断の最優先に置くのか考えてみましょう。
効率的に意思決定を行うにはどうすればよいでしょうか? 機能の順序

2. 決定木の分類原理の詳細な説明

1. 問題の例を使ってみましょう

ある人に貸すかどうかを予測するには4つの特徴量があることが知られています
(1)まず家を見て、次に仕事を見る --> 貸すかどうか (2つの特徴だけを見ます
) 2) 年齢、信用状況、職業 --> 参照 3 つの特徴が含まれています。2
番目の方法は最初の方法ほど効率的ではありません。最初
にどの特徴を見るべきかを迅速かつ自動的に決定する数学的方法を見つけたいと考えています。

2. 情報理論の基礎 情報
エントロピーや情報ゲインなどの情報理論の知識を導入する必要があります!

(1) 情報
シャノンの定義:ランダムな不確実性を排除するもの
シャオ・ミンの年齢「私は今年18歳です」
シャオ・ファ「シャオ・ミンは来年19歳です」

シャオ・ミンが言った後、シャオ・ファの言ったことは情報ではなくナンセンスになった。

(2) 情報量-情報エントロピーの測定

3. 情報エントロピーの定義
H の専門用語は情報エントロピーと呼ばれ、その単位はビットです。

4. 銀行融資データを例として、情報エントロピーを計算します。
誰かの年齢、職業、家、信用状況がわかっている場合、あなたはこの人に融資しますか?
不確実性の大きさを測定する必要がある
ここでは融資がある場合と融資がない場合の 2 つの状況があり、融資がない
確率は 6/15、融資される確率は 9/15
H (合計) = -(6/15 * 6/15 の対数 + 9/15 * 9/15 の対数) = 0.971

ある特徴を知ると不確実性が減りますので、
ある特徴を知った後にどの程度不確実性が減るかを知ることができればと思います。どの特徴がわかった上で再度比較すると、不確実性が最も軽減されます。まずはこの機能を見てもらえますか?

ある特徴を知った後、その情報エントロピーはいくらでしょうか?
はじめに - 情報の獲得

5. 情報ゲイン:
決定木を分割するための基礎の 1 つ - 情報ゲイン

(1) 定義と計算式
学習データセット D 上の特徴 A の情報利得 g(D,A) を、セット D の情報エントロピー H(D) と情報条件付きエントロピー H(D| A の差) として定義します。
g(D,A) = H(D) - 条件付きエントロピー H(D|A)
情報ゲインは、特定の特徴を知った後にその不確実性がどの程度低減されるかを測定します。

年齢がわかった後の情報利得を計算します:
g(D,age) = H(D) - H(D|age)

H(D|年齢)を求めます:
H(若者) = -(2/5 * log 2/5 + 3/5 * log 3/5) = 
H(中年) = -(2/5 * log 2/ 5 + 3/5 * log 3/5) = 
H(老年期) = -(1/5 * log 1/5 + 4/5 * log 4/5) = 
H(D|年齢) = 1/3 * H(若者) + 1/3 * H (中年) + 1/3 * H (高齢者)

年齢、職業、持ち家、ローン状況をA1、A2、A3、A4で表します。最終的な計算結果は、g(D, A1) = 0.313、g(D, A2) = 0.324、g(D, A3) = 0.420、g(D, A4) = 0.363 となります。そこで、分割の最初の特徴として A3 を選択します。

(2)公式

(3) もちろん、決定木の原理は情報利得だけではなく、他の方法も同様です。
ID3:
  情報利得、最大の基準
C4.5:
  情報利得比、最大の基準
CART:
  分類木: ジニ係数、最小基準、sklearn では、除算のデフォルトの原理利点を選択できます
  。除算はより詳細になります (次の例から理解できます)。

3. デシジョンツリー API

1. API
クラス sklearn.tree.DecisionTreeClassifier(criterion='gini', max_ Depth=None, random_state=None)
デシジョン ツリー アナライザーの
基準: デフォルトは 'gini' 係数ですが、情報ゲインのエントロピー 'entropy' を選択することもできます。
max_ Depth:tree ツリーの深さが深すぎる
  ため、過学習が発生します。
  過学習により、モデルの汎化能力が低下します。つまり、モデルは現在のサンプルセットに過度に適しており、(予測に)適応する能力が不足します。 ) 新しいサンプルrandom_state:
乱数シード

2. アヤメの花の決定木分類

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.tree import DecisionTreeClassifier

def KNN_iris():
    """
    用KNN算法对鸢尾花进行分类
    """
    # 1、获取数据
    iris = load_iris()
    print("iris.data:\n", iris.data)
    print("iris.target:\n", iris.target)
    # 2、划分数据集
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)
    # 3、特征工程:标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    # 用训练集的平均值和标准差对测试集的数据来标准化
    # 这里测试集和训练集要有一样的平均值和标准差,而fit的工作就是计算平均值和标准差,所以train的那一步用fit计算过了,到了test这就不需要再算一遍自己的了,直接用train的就可以
    x_test = transfer.transform(x_test)
    # 4、KNN算法预估器
    estimator = KNeighborsClassifier(n_neighbors=3)
    estimator.fit(x_train, y_train)
    # 5、模型评估
    # 方法1:直接比对真实值和预测值
    y_predict = estimator.predict(x_test)
    print("y_predict:\n", y_predict)
    print("直接比对真实值和预测值:\n", y_test == y_predict)
    # 方法2:计算准确率
    score = estimator.score(x_test, y_test)
    print("准确率为:\n", score)
    return None
 
def KNN_iris_gscv():
    """
    用KNN算法对鸢尾花进行分类,添加网格搜索和交叉验证
    """
    # 1、获取数据
    iris = load_iris()
    print("iris.data:\n", iris.data)
    print("iris.target:\n", iris.target)
    # 2、划分数据集
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)
    # 3、特征工程:标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    # 用训练集的平均值和标准差对测试集的数据来标准化
    # 这里测试集和训练集要有一样的平均值和标准差,而fit的工作就是计算平均值和标准差,所以train的那一步用fit计算过了,到了test这就不需要再算一遍自己的了,直接用train的就可以
    x_test = transfer.transform(x_test)
    # 4、KNN算法预估器
    estimator = KNeighborsClassifier()
    # 加入网格搜索和交叉验证
    # 参数准备
    param_dict = {"n_neighbors": [1, 3, 5, 7, 9, 11]}
    estimator = GridSearchCV(estimator, param_grid=param_dict, cv=10)
    estimator.fit(x_train, y_train)
    # 5、模型评估
    # 方法1:直接比对真实值和预测值
    y_predict = estimator.predict(x_test)
    print("y_predict:\n", y_predict)
    print("直接比对真实值和预测值:\n", y_test == y_predict)
    # 方法2:计算准确率
    score = estimator.score(x_test, y_test)
    print("准确率为:\n", score)
    #最佳参数:best_params_
    print("最佳参数:\n", estimator.best_params_)
    #最佳结果:best_score_
    print("最佳结果:\n", estimator.best_score_)
    #最佳估计器:best_estimator_
    print("最佳估计器:\n", estimator.best_estimator_)
    #交叉验证结果:cv_results_
    print("交叉验证结果:\n", estimator.cv_results_)
    return None

def nb_news():
    """
    用朴素贝叶斯算法对新闻进行分类
    """
    # 1、获取数据
    news = fetch_20newsgroups(subset="all")
    # 2、划分数据集
    x_train, x_test, y_train, y_test = train_test_split(news.data, news.target)
    # 3、特征工程:文本特征抽取-tfidf
    transfer = TfidfVectorizer()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.transform(x_test)
    # 4、朴素贝叶斯算法预估器流程
    estimator = MultinomialNB()
    estimator.fit(x_train, y_train)
    # 5、模型评估
    # 方法1:直接比对真实值和预测值
    y_predict = estimator.predict(x_test)
    print("y_predict:\n", y_predict)
    print("直接比对真实值和预测值:\n", y_test == y_predict)
    # 方法2:计算准确率
    score = estimator.score(x_test, y_test)
    print("准确率为:\n", score)
    return None

def decision_iris():
    """
    用决策树对鸢尾花数据进行分类
    """
    # 1、获取数据集
    iris = load_iris()
    # 2、划分数据集
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)
    # 3、决策树预估器
    estimator = DecisionTreeClassifier(criterion='entropy')
    estimator.fit(x_train, y_train)
    # 4、模型评估
    # 方法1:直接比对真实值和预测值
    y_predict = estimator.predict(x_test)
    print("y_predict:\n", y_predict)
    print("直接比对真实值和预测值:\n", y_test == y_predict)
    # 方法2:计算准确率
    score = estimator.score(x_test, y_test)
    print("准确率为:\n", score)
    return None

if __name__ == "__main__":
    # 代码1:用KNN算法对鸢尾花进行分类
    KNN_iris()
    # 代码2:用KNN算法对鸢尾花进行分类,添加网格搜索和交叉验证
    #KNN_iris_gscv()
    # 代码3:用朴素贝叶斯算法对新闻进行分类
    #nb_news()
    # 代码4:用决策树对鸢尾花数据进行分类
    decision_iris()

操作結果:

y_predict:
 [0 2 0 0 2 1 1 0 2 1 2 1 2 2 1 1 2 1 1 0 0 2 0 0 1 1 1 2 0 1 0 1 0 0 1 2 1
 2]
直接比对真实值和预测值:
 [ True  True  True  True  True  True False  True  True  True  True  True
  True  True  True False  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True False  True
  True  True]
准确率为:
 0.9210526315789473
y_predict:
 [0 2 0 0 2 1 1 0 2 1 2 1 2 2 1 1 2 1 1 0 0 2 0 0 1 1 1 2 0 1 0 1 0 0 1 2 1
 2]
直接比对真实值和预测值:
 [ True  True  True  True  True  True False  True  True  True  True  True
  True  True  True False  True  True  True  True  True  True  True  True
  True  True  True  True  True  True  True  True  True  True False  True
  True  True]
准确率为:
 0.9210526315789473

KNN は遅延アルゴリズムです。計算中に、メモリ内の各サンプル間の距離を必死に計算します。デシジョン
ツリー アプリケーション シナリオは、データ量が比較的大きい状況での使用に適しています。

4. 決定木の可視化

1. ツリー構造をドット ファイルに保存します
sklearn.tree.export_graphviz()
この関数は DOT 形式をエクスポートできます。

2.tree.export_graphviz(estimator, out_file='tree.dot', feature_names=['',''])
estimator: 推定子オブジェクト
out_file: エクスポートされた名前
feature_names: 特徴の名前

3. コードを変更する

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.tree import DecisionTreeClassifier, export_graphviz

def KNN_iris():
    """
    用KNN算法对鸢尾花进行分类
    """
    # 1、获取数据
    iris = load_iris()
    print("iris.data:\n", iris.data)
    print("iris.target:\n", iris.target)
    # 2、划分数据集
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)
    # 3、特征工程:标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    # 用训练集的平均值和标准差对测试集的数据来标准化
    # 这里测试集和训练集要有一样的平均值和标准差,而fit的工作就是计算平均值和标准差,所以train的那一步用fit计算过了,到了test这就不需要再算一遍自己的了,直接用train的就可以
    x_test = transfer.transform(x_test)
    # 4、KNN算法预估器
    estimator = KNeighborsClassifier(n_neighbors=3)
    estimator.fit(x_train, y_train)
    # 5、模型评估
    # 方法1:直接比对真实值和预测值
    y_predict = estimator.predict(x_test)
    print("y_predict:\n", y_predict)
    print("直接比对真实值和预测值:\n", y_test == y_predict)
    # 方法2:计算准确率
    score = estimator.score(x_test, y_test)
    print("准确率为:\n", score)
    return None
 
def KNN_iris_gscv():
    """
    用KNN算法对鸢尾花进行分类,添加网格搜索和交叉验证
    """
    # 1、获取数据
    iris = load_iris()
    print("iris.data:\n", iris.data)
    print("iris.target:\n", iris.target)
    # 2、划分数据集
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)
    # 3、特征工程:标准化
    transfer = StandardScaler()
    x_train = transfer.fit_transform(x_train)
    # 用训练集的平均值和标准差对测试集的数据来标准化
    # 这里测试集和训练集要有一样的平均值和标准差,而fit的工作就是计算平均值和标准差,所以train的那一步用fit计算过了,到了test这就不需要再算一遍自己的了,直接用train的就可以
    x_test = transfer.transform(x_test)
    # 4、KNN算法预估器
    estimator = KNeighborsClassifier()
    # 加入网格搜索和交叉验证
    # 参数准备
    param_dict = {"n_neighbors": [1, 3, 5, 7, 9, 11]}
    estimator = GridSearchCV(estimator, param_grid=param_dict, cv=10)
    estimator.fit(x_train, y_train)
    # 5、模型评估
    # 方法1:直接比对真实值和预测值
    y_predict = estimator.predict(x_test)
    print("y_predict:\n", y_predict)
    print("直接比对真实值和预测值:\n", y_test == y_predict)
    # 方法2:计算准确率
    score = estimator.score(x_test, y_test)
    print("准确率为:\n", score)
    #最佳参数:best_params_
    print("最佳参数:\n", estimator.best_params_)
    #最佳结果:best_score_
    print("最佳结果:\n", estimator.best_score_)
    #最佳估计器:best_estimator_
    print("最佳估计器:\n", estimator.best_estimator_)
    #交叉验证结果:cv_results_
    print("交叉验证结果:\n", estimator.cv_results_)
    return None

def nb_news():
    """
    用朴素贝叶斯算法对新闻进行分类
    """
    # 1、获取数据
    news = fetch_20newsgroups(subset="all")
    # 2、划分数据集
    x_train, x_test, y_train, y_test = train_test_split(news.data, news.target)
    # 3、特征工程:文本特征抽取-tfidf
    transfer = TfidfVectorizer()
    x_train = transfer.fit_transform(x_train)
    x_test = transfer.transform(x_test)
    # 4、朴素贝叶斯算法预估器流程
    estimator = MultinomialNB()
    estimator.fit(x_train, y_train)
    # 5、模型评估
    # 方法1:直接比对真实值和预测值
    y_predict = estimator.predict(x_test)
    print("y_predict:\n", y_predict)
    print("直接比对真实值和预测值:\n", y_test == y_predict)
    # 方法2:计算准确率
    score = estimator.score(x_test, y_test)
    print("准确率为:\n", score)
    return None

def decision_iris():
    """
    用决策树对鸢尾花数据进行分类
    """
    # 1、获取数据集
    iris = load_iris()
    # 2、划分数据集
    x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)
    # 3、决策树预估器
    estimator = DecisionTreeClassifier(criterion='entropy')
    estimator.fit(x_train, y_train)
    # 4、模型评估
    # 方法1:直接比对真实值和预测值
    y_predict = estimator.predict(x_test)
    print("y_predict:\n", y_predict)
    print("直接比对真实值和预测值:\n", y_test == y_predict)
    # 方法2:计算准确率
    score = estimator.score(x_test, y_test)
    print("准确率为:\n", score)
    # 可视化决策树
    export_graphviz(estimator, out_file='iris_tree.dot', feature_names=iris.feature_names)
    return None

if __name__ == "__main__":
    # 代码1:用KNN算法对鸢尾花进行分类
    #KNN_iris()
    # 代码2:用KNN算法对鸢尾花进行分类,添加网格搜索和交叉验证
    #KNN_iris_gscv()
    # 代码3:用朴素贝叶斯算法对新闻进行分类
    #nb_news()
    # 代码4:用决策树对鸢尾花数据进行分类
    decision_iris()

iris_tree.dot ファイルは、以下の実行後に生成されます。

digraph Tree {
node [shape=box] ;
0 [label="petal width (cm) <= 0.8\nentropy = 1.584\nsamples = 112\nvalue = [38, 38, 36]"] ;
1 [label="entropy = 0.0\nsamples = 38\nvalue = [38, 0, 0]"] ;
0 -> 1 [labeldistance=2.5, labelangle=45, headlabel="True"] ;
2 [label="petal width (cm) <= 1.65\nentropy = 0.999\nsamples = 74\nvalue = [0, 38, 36]"] ;
0 -> 2 [labeldistance=2.5, labelangle=-45, headlabel="False"] ;
3 [label="sepal length (cm) <= 7.1\nentropy = 0.179\nsamples = 37\nvalue = [0, 36, 1]"] ;
2 -> 3 ;
4 [label="entropy = 0.0\nsamples = 36\nvalue = [0, 36, 0]"] ;
3 -> 4 ;
5 [label="entropy = 0.0\nsamples = 1\nvalue = [0, 0, 1]"] ;
3 -> 5 ;
6 [label="petal length (cm) <= 5.05\nentropy = 0.303\nsamples = 37\nvalue = [0, 2, 35]"] ;
2 -> 6 ;
7 [label="sepal width (cm) <= 2.9\nentropy = 0.863\nsamples = 7\nvalue = [0, 2, 5]"] ;
6 -> 7 ;
8 [label="entropy = 0.0\nsamples = 4\nvalue = [0, 0, 4]"] ;
7 -> 8 ;
9 [label="petal width (cm) <= 1.75\nentropy = 0.918\nsamples = 3\nvalue = [0, 2, 1]"] ;
7 -> 9 ;
10 [label="entropy = 0.0\nsamples = 1\nvalue = [0, 1, 0]"] ;
9 -> 10 ;
11 [label="sepal width (cm) <= 3.1\nentropy = 1.0\nsamples = 2\nvalue = [0, 1, 1]"] ;
9 -> 11 ;
12 [label="entropy = 0.0\nsamples = 1\nvalue = [0, 0, 1]"] ;
11 -> 12 ;
13 [label="entropy = 0.0\nsamples = 1\nvalue = [0, 1, 0]"] ;
11 -> 13 ;
14 [label="entropy = 0.0\nsamples = 30\nvalue = [0, 0, 30]"] ;
6 -> 14 ;
}

4. 生成されたイメージ
http://webgraphviz.com に
は、常に「loading...」と表示されます。

その後、オンラインで生成されたものを見つけました。http
://www.tasksteper.com:8099/flow/home/ にアクセスし、ユーザー名/パスワード: testuser1/testuser1 でログインし、「統合ツール」プロジェクトに入り、「エントリーの作成」をクリックします。 」

5. 判定プロセス
(1) まず花びらの幅を見て、幅が 0.8 以下であれば
(2) 満足できない場合は分割を続けます
(3) エントロピー: 情報ゲインを計算します
(4) サンプル:サンプルの数

5. デシジョンツリーの長所と短所

1. ある程度
シンプルで分かりやすく、視覚化できる
視覚化 - 強い解釈性

2. 欠点:
ツリーは複雑すぎるため、過剰適合する傾向があります。

3.
ブランチ削減カート アルゴリズムが改善され、デシジョン ツリー API に
ランダム フォレストが実装されました。
 

おすすめ

転載: blog.csdn.net/csj50/article/details/132732152