機械学習アルゴリズムの実践: ナイーブベイズ

機械学習アルゴリズムの実践: ナイーブベイズ

[[197761]]

序文

前回の記事「機械学習アルゴリズムの実践: 決定木」では、決定木の実装についてまとめました。この記事では、単純ベイズ分類器を段階的に実装し、SMS スパム コーパスのデータを使用してモデルをトレーニングし、スパム メッセージをフィルタリングし、最後に分類エラー率を計算します。

文章

決定木分類や k 最近傍分類アルゴリズムとは異なり、ベイズ分類は主に確率論の知識に依存して、各タイプに属する提供されたデータの条件付き確率を比較し、それらを個別に計算し、条件付き確率が最も高いカテゴリが最適なカテゴリであると予測します。もちろん、サンプルの数が増えれば増えるほど、カウントできるさまざまな種類の特徴値の分布がより正確になり、この分布を使用して行われる予測もより正確になります。

ベイズ基準

単純ベイズ分類器の中核となるのはベイズ基準であり、次の式で表されます。

この式は、結合確率によってリンクされた 2 つの交換可能な条件付き確率の関係を表しており、p(B|A) がわかっている場合に p(A|B) を計算できます。ベイジアン モデルは、ベイジアン基準を使用して、さまざまなカテゴリ条件下でのサンプルの条件付き確率を計算し、最も高い条件付き確率を持つタイプを分類予測結果として取得します。

分類に条件付き確率を使用する

ここで、条件付き確率による分類方法を簡単に紹介します。ある人物の背中を見て、その特徴(データ)に基づいて性別(カテゴリ)を判断したいとします。その特徴とは、髪が長いかどうか、身長が170cm以上かどうか、足が細いかどうか、スカートを履いているかどうかなどです。後ろの図を見ると、上記の特徴を記述する特徴ベクトルが得られます(1ははい、0はいいえを意味します):ω=[0,1,1,0]

ベイズ分類は、次の 2 つの条件付き確率を比較します。

  • p(男性|ω)は、ωが[0,1,1,0に等しい条件下で、その人が男性である確率である。
  • p(girl|ω))、ωが[0,1,1,0]に等しい条件下でその人が女の子である確率

p(boy|ω)>p(girl|ω)の場合、その人は男の子とみなされ、そうでない場合は女の子とみなされます。

では、p(男|ω)をどのように見つけるのでしょうか? これにはベイズ基準が必要です。

ベイズの基準によれば、

もっと分かりやすく言うと、

特徴が互いに独立している場合(条件付き独立仮定)、上記の条件付き確率は次のように書き直すことができます。

このようにして、現在の後ろ姿が男の子か女の子かの条件付き確率を計算できます。

独自のベイズ分類器を実装する

ベイズ分類器の実装は非常に簡単です。以下では、テキスト分類を目的とした単純ベイズテキスト分類器を Python を使用して実装します。

条件付き確率を計算するには、異なるカテゴリにおける各特徴の条件付き確率と、そのタイプの周辺確率を計算する必要があります。そのためには、大量のトレーニング データの統計を通じて近似値を取得する必要があります。これは、ナイーブ ベイズ モデルをトレーニングするプロセスです。

さまざまなテキストについて、データ特徴ベクトルとして表示されるすべての単語を取得し、各テキストに表示される用語の数(または特定の用語が表示されるかどうか)をデータベクトルとしてカウントできます。このようなテキストは整数のリストに処理することができ、その長さはすべてのエントリの数になります。このベクトルは非常に長くなる可能性があります。この記事で使用されているデータ セット内のテキスト メッセージ エントリの合計は 3,000 語を超えます。

  1. def get_doc_vector(単語、語彙):
  2.  
  3. '' ' 文書内の用語を語彙に従って文書ベクトルに変換する
  4.  
  5.   
  6.  
  7. :param words: 文書内の単語のリスト
  8.  
  9. :type words:文字リスト
  10.  
  11.   
  12.  
  13. :param vocabulary: 総語彙リスト
  14.  
  15. :type 語彙:文字リスト
  16.  
  17.   
  18.  
  19. : doc_vectを返す: ベイズ分析のための文書ベクトル
  20.  
  21. :type doc_vect:リスト 整数 
  22.  
  23. '' '
  24.  
  25. doc_vect = [0]*len(語彙)
  26.  
  27.   
  28.  
  29. 単語単語:
  30.  
  31. 語彙内の単語:
  32.  
  33. idx =語彙.インデックス(単語)
  34.  
  35. doc_vect[idx] = 1
  36.  
  37.   
  38.  
  39. doc_vectを返す

統計トレーニング プロセスのコード実装は次のとおりです。

  1. def train(自分自身、データセット、クラス):
  2.  
  3. '' 'ナイーブベイズモデルのトレーニング
  4.  
  5.   
  6.  
  7. :param データセット: すべてのドキュメントデータベクトル
  8.  
  9. :type dataset:すべてのドキュメントベクトルを含む MxN 行列。
  10.  
  11.   
  12.  
  13. :param クラス: すべてのドキュメントタイプ
  14.  
  15. :type クラス: 1xN リスト
  16.  
  17.   
  18.  
  19. : return cond_probs: トレーニングで得られた条件付き確率行列
  20.  
  21. :type cond_probs: 辞書
  22.  
  23.   
  24.  
  25. : cls_probsを返す: さまざまなタイプの確率
  26.  
  27. :type cls_probs: 辞書
  28.  
  29. '' '
  30.  
  31. # メモリの種類別に分類
  32.  
  33. サブデータセット = defaultdict(lambda: [])
  34.  
  35. cls_cnt = デフォルト辞書(ラムダ: 0)
  36.  
  37.   
  38.  
  39. doc_vect、clszip(データセット、クラス)格納する場合:
  40.  
  41. サブデータセット[cls].append(doc_vect)
  42.  
  43. cls_cnt[cls] += 1
  44.  
  45.   
  46.  
  47. # タイプ確率を計算する
  48.  
  49. cls_probs = {k: v/len(classes) 、k、v の場合、cls_cnt.items()}
  50.  
  51.   
  52.  
  53. # さまざまな条件付き確率を計算する
  54.  
  55. 条件問題 = {}
  56.  
  57. データセット = np.array(データセット)
  58.  
  59. clsの場合sub_datasets.items()内のsub_dataset:
  60.  
  61. サブデータセット = np.array(サブデータセット)
  62.  
  63. # 分類器を改善します。
  64.  
  65. cond_prob_vect = np.log(( np.sum (sub_dataset, axis=0) + 1)/(np.sum ( dataset) + 2))
  66.  
  67. 条件問題[cls] = 条件問題ベクトル
  68.  
  69.   
  70.  
  71. cond_probs、cls_probsを返す

ここでは、条件付き確率の基本的な直接乗算に 2 つの改善が加えられていることに注意してください。

  1. 各特徴の確率の初期値は 1 であり、分母にある特定のタイプのサンプルの総数の初期値も 1 です。これは、特徴の確率が 0 の場合、結合確率も 0 になるという状況を回避するためです。これは当然意味がありません。トレーニング サンプルが十分に大きい場合、比較結果には影響しません。
  2. 各独立特徴の確率は 1 未満であるため、累積すると必然的にブックが小さくなり、浮動小数点アンダーフローの問題が発生します。したがって、ここではすべての確率の対数を取り、損失がないことを確認しながらアンダーフローの問題を回避します。

統計的確率情報を取得したら、ベイズ基準を使用してデータのタイプを予測できます。ここでは、各状況の確率を直接計算するのではなく、統計ベクトルとデータベクトルの内積を実行して条件付き確率の相対値を取得し、相対比較を行って決定を下しました。

  1. def classify(self, doc_vect, cond_probs, cls_probs):
  2.  
  3. '' ' Naive Bayes を使用して doc_vect を分類します。
  4.  
  5. '' '
  6.  
  7. 予測確率 = {}
  8.  
  9. cls、 cls_probs.items()内のcls_probの場合:
  10.  
  11. 条件問題ベクトル = 条件問題[cls]
  12.  
  13. pred_probs[cls] = np.sum (cond_prob_vect*doc_vect) + np.log(cls_prob)
  14.  
  15. 戻る 最大(pred_probs、キー= pred_probs.get)

SMSメッセージを分類する

Naive Bayes モデルを構築したので、これを使用して統計を収集し、予測を行うことができます。ここでは、SMS スパム コーパスからスパム データを使用し、データの 90% をトレーニング データとしてランダムに抽出し、残りの 10% のデータをテスト データとして抽出して、ベイジアン モデル予測の精度をテストしました。

もちろん、モデルを構築する前に、モデルが処理できる形式にデータを処理する必要があります。

  1. エンコーディング = 'ISO-8859-1'  
  2.  
  3. トレーニングの割合 = 0.9
  4.  
  5.   
  6.  
  7. def get_doc_vector(単語、語彙):
  8.  
  9. '' ' 文書内の用語を語彙に従って文書ベクトルに変換する
  10.  
  11.   
  12.  
  13. :param words: 文書内の単語のリスト
  14.  
  15. :type words:文字リスト
  16.  
  17.   
  18.  
  19. :param vocabulary: 総語彙リスト
  20.  
  21. :type 語彙:文字リスト
  22.  
  23.   
  24.  
  25. : doc_vectを返す: ベイズ分析のための文書ベクトル
  26.  
  27. :type doc_vect:リスト 整数 
  28.  
  29. '' '
  30.  
  31. doc_vect = [0]*len(語彙)
  32.  
  33.   
  34.  
  35. 単語単語:
  36.  
  37. 語彙内の単語:
  38.  
  39. idx =語彙.インデックス(単語)
  40.  
  41. doc_vect[idx] = 1
  42.  
  43.   
  44.  
  45. doc_vectを返す
  46.  
  47.   
  48.  
  49. def parse_line(行):
  50.  
  51. '' ' データセット内の各行を解析し、用語ベクトルと SMS タイプを返します。
  52.  
  53. '' '
  54.  
  55. cls = 行を分割します( ',' )[-1].strip()
  56.  
  57. コンテンツ = ',' . join (line.split( ',' )[: -1])
  58.  
  59. word_vect = [ word.lower ()wordの場合re.split (r '\W+' 、 content) 、 word の場合]
  60.  
  61. word_vect、clsを返す
  62.  
  63.   
  64.  
  65. def parse_file(ファイル名):
  66.  
  67. '' ' ファイル内のデータを解析する
  68.  
  69. '' '
  70.  
  71. 語彙、単語ベクトル、クラス = []、[]、[]
  72.  
  73.   open (filename, 'r' , encoding=ENCODING)f:として開きます。
  74.  
  75. fの場合:
  76.  
  77. 行の場合:
  78.  
  79. word_vect, cls = parse_line(行)
  80.  
  81. 語彙を拡張します(word_vect)
  82.  
  83. word_vects.append(word_vect)
  84.  
  85. クラス.append(cls)
  86.  
  87. 語彙 = リスト(セット(語彙))
  88.  
  89.   
  90.  
  91. 語彙、word_vects、クラスを返す

上記の 3 つの関数を使用すると、テキストをモデルに必要なデータ ベクトルに直接変換できます。その後、データ セットを分割し、統計用のベイジアン モデルにトレーニング データ セットを渡すことができます。

  1. # トレーニングデータとテストデータ
  2.  
  3. ntest = int (len(クラス)*(1-TRAIN_PERCENTAGE))
  4.  
  5.   
  6.  
  7. テストワードベクトル = []
  8.  
  9. テストクラス = []
  10.  
  11. i が範囲(ntest)場合:
  12.  
  13. idx = ランダム.randint(0, len(word_vects)-1)
  14.  
  15. test_word_vects.append(word_vects.pop(idx))
  16.  
  17. test_classes.append(classes.pop(idx))
  18.  
  19.   
  20.  
  21. train_word_vects = 単語ベクトル
  22.  
  23. train_classes = クラス
  24.  
  25.   
  26.  
  27. train_dataset = [ train_word_vects内の単語get_doc_vector(words, vocabulary)]

モデルをトレーニングします。

  1. cond_probs、cls_probs = clf.train(train_dataset、train_classes)

次に、テスト データを使用して、ベイズ モデルの予測精度をテストします。

  1. # モデルをテストする
  2.  
  3. エラー = 0
  4.  
  5. zip(test_word_vects, test_classes)内のtest_word_vect、test_clsの場合:
  6.  
  7. test_data = get_doc_vector(test_word_vect、語彙)
  8.  
  9. pred_cls = clf.classify(テストデータ、条件問題、cls_probs)
  10.  
  11. test_cls != pred_cls の場合:
  12.  
  13. print( '予測: {} -- 実際: {}' .format(pred_cls, test_cls))
  14.  
  15. エラー += 1
  16.  
  17.   
  18.  
  19. print( 'エラー率: {}' .format(error/len(test_classes)))

4つのグループをランダムにテストしたところ、エラー率は0、0.037、0.015、0でした。平均エラー率は1.3%でした。

テストの後、さまざまな種類のテキスト メッセージにおける各用語の確率分布がどのようになっているかを確認してみましょう。

  1. # さまざまな種類の確率分布曲線を描く
  2.  
  3. 図 = plt.figure()
  4.  
  5. ax = fig.add_subplot(111)
  6.  
  7. cond_probs.items ()cls、probsの場合:
  8.  
  9. ax.scatter(np.arange(0, len(probs)),
  10.  
  11. 確率*cls_確率[cls],
  12.  
  13. ラベル=cls、
  14.  
  15. アルファ=0.3)
  16.  
  17. ax.凡例()
  18.  
  19.   
  20.  
  21. plt.show()

決定木を試す

前回の記事では、ID3アルゴリズムに基づいて決定木を実装しました。これも分類問題です。テキストデータを使用して、テキストメッセージを分類するための決定木を構築することもできます。もちろん、唯一の厄介なことは、ベイズと同じベクトルをデータとして使用すると、属性が多くなる可能性があることです。決定木を構築すると、ツリー構造の各レイヤーが属性を再帰的にトラバースし、情報ゲインに応じてツリー分割に最適な属性を選択します。このように、多くの属性は決定木を構築するプロセスに時間がかかる可能性があります。それでは試してみましょう...

  1. # 決定木を生成する
  2.  
  3. os.path.exists( 'sms_tree.pkl' )が存在しない場合は:
  4.  
  5. clf.create_tree(トレーニングデータセット、トレーニングクラス、語彙)
  6.  
  7. clf.dump_tree( 'sms_tree.pkl' )
  8.  
  9. それ以外
  10.  
  11. clf.load_tree( 'sms_tree.pkl' ) は
  12.  
  13.   
  14.  
  15. # モデルをテストする
  16.  
  17. エラー = 0
  18.  
  19. zip(test_word_vects, test_classes)内のtest_word_vect、test_clsの場合:
  20.  
  21. test_data = get_doc_vector(test_word_vect、語彙)
  22.  
  23. pred_cls = clf.classify(テストデータ、feat_names=語彙)
  24.  
  25. test_cls != pred_cls の場合:
  26.  
  27. print( '予測: {} -- 実際: {}' .format(pred_cls, test_cls))
  28.  
  29. エラー += 1
  30.  
  31.   
  32.  
  33. print( 'エラー率: {}' .format(error/len(test_classes)))

ランダムに2回テストしたところ、エラー率は0.09、0.0でした。

効果はかなり良いです

Graphviz を使って、決定木によって判断基準としてどのような用語が選択されているかを可視化してみましょう(このとき決定木のメリットが反映されます)。

決定木の深さがあまり深くないことがわかります。分類の種類が多い場合、深さが増すと決定木が面倒になる可能性があると推測されます。

要約する

この記事では、Python を使用して Naive Bayes 分類器を段階的に実装し、スパム テキスト メッセージをフィルタリングします。また、同じデータに対する決定木の分類効果との簡単な比較も行います。この記事に関連するコード実装: https://github.com/PytLab/MLBox/tree/master/naive_bayes 。スパムメッセージをフィルタリングする決定木スクリプトは https://github.com/PytLab/MLBox/tree/master/decision_tree にあります。

参照する

  • 機械学習の実践
  • ベイズ推論の原理を説明する例
  • シンプルこそが道: ナイーブベイズ分類器

関連資料

  • 機械学習アルゴリズムの実践 - 決定木

<<:  人工知能やビッグデータ製品の開発において、特に注意すべき点は何でしょうか?

>>:  Yunqi CapitalのChen Yu氏:AI投資家を惹きつけてターゲットにする方法

ブログ    
ブログ    

推薦する

CNN、RNN、GAN とは何ですか?ついに誰かが明らかにした

[[334740]] 01 完全に接続されたネットワーク完全に接続された高密度の線形ネットワークは、...

重要インフラのサイバーセキュリティリスク管理における AI の影響

AIがサイバー攻撃から重要なインフラを守るためにどう役立つか 電力網、水道システム、交通網などの重要...

自然言語の事前トレーニングを10倍高速化する方法

近年、自然言語処理における事前トレーニングは研究分野でホットな話題となっており、有名なGPT-3も新...

...

AI医用画像の春が再び到来?

概要: AI医用画像診断市場は急速な成長期を迎えつつあり、医師の負担を軽減しながら医療の質の向上も期...

このGitHubの8000スターAIリアルタイム顔変換プロジェクトにはアプリがある

人間のロールプレイングへの熱意は決して衰えることがなく、だからこそ AI による顔の変形が人気を博し...

AIの頂点:プレミアムディープラーニングGPU、KG 7204-R5

人工知能(AI)の分野といえば、「人間対機械」ゲームにおける「AlphaGo」という名の名を挙げざる...

コグニティブ時代のIBMの新しいカスタマーサービスセンターは、人間と機械のコラボレーションでより大きな価値を生み出します

これは厳しい試練となるだろう年初に突然発生した疫病は、世界に「一時停止ボタン」を押し、伝統的な運営モ...

...

中国の「データブリックス」:AIインフラの構築に真剣に取り組む

AI導入の最大の推進要因はインフラのアップグレードです。近年、ビッグデータ分析やAIなどの分野が注目...

ロボットは「痛みを恐れ」始めており、人間の介入なしに「自分自身を癒す」こともできる。

[[348121]]私の印象では、ロボットは火や剣を恐れていないようです。彼らには痛覚はなく、単な...

WeChat、サードパーティのエコシステムに統合するインテリジェント会話システム「Xiaowei」を発表

2019年WeChatオープンクラスPROで、WeChat AIチームが開発したインテリジェント対話...

貪欲アルゴリズム: K回の反転後の配列の合計を最大化する

[[355496]]多くのレコーディング仲間が、昨日のトピック「貪欲アルゴリズム:ジャンピングゲーム...

...