ベイジアン決定分類アルゴリズム
1. 実験目的
(1) Naive Bayes 意思決定アルゴリズムに精通している。
(2) AllElectronics 顧客データベースにクエリを実行して、事前確率とクラス条件付き確率を取得します。
(3) 単純ベイズ アルゴリズムを使用してサンプル セットを分類するプログラムを作成し、タスク関連データに対して単純ベイズ分類アルゴリズムを実行し、実験をデバッグします。
(4) 実験レポートを書きます。
2. 実験原理
1. 事前確率とクラス条件付き確率
事前確率: 事前確率は、 C i C_iに属するトレーニング サンプル セットとして定義されます。C私はクラスのサンプル(タプル)数と総サンプル数N i N_iN私は比率はP ( C i ) = Ni NP(C_i)=\frac{N_i}{N}として記録されます。P ( C私は)=NN私は。
クラス条件付き確率: クラス条件付き確率は、 C i C_iに属するトレーニング サンプル セットとして定義されます。C私はXXの特徴を持つクラスX ni n_iのサンプル (タプル) の数n私はC i C_iに属しますC私はクラスN i N_iのサンプル (タプル) の数N私は比率はP (P ( X ∣ C私は)=N私はn私は。
2. ベイズ主義の意思決定
ベイジアン決定 (分類) 方法では、サンプル (タプル) をC i C_iに割り当てます。C私はクラス、P ( C_i)>P(X|C_j)P(C_j) の場合に限り
、1\leq j\leq m、j\neq i に対してP ( X ∣ C私は) P ( C私は)>P ( X ∣ Cj) P ( Cj)、ペア1≤j≤メートル、j=i
のうち、トレーニング サンプル セット内のサンプル (タプル) はmmmカテゴリー。
3. 実験内容と手順
1. 実験内容
ベイジアン分類器を使用して、既知の特徴ベクトル X を分類します。
- AllElectronics 顧客データベース クラスによってラベル付けされたトレーニング サンプル セット (タプル) は、事前
確率 P(Ci) とクラス条件付き確率 P(X|Ci) を計算するようにプログラムされており、キー コードの機能と実装方法は次のとおりです。実験報告書; - ベイズ分類法プログラミングを使用して特徴ベクトル X を分類し、実験レポートで
主要なプログラム断片の機能と実装方法を指摘します。 - テストサンプルを使用して分類エラー率を推定します。
- 実験レポートにプログラムまたはルーチンのブロック図を描きます。
2. 実験手順
この分類問題は、顧客がコンピュータを購入する傾向があるかどうかを判断するものであるため、C1 は buys_computer=yes に対応し、C2 は buys_computer=no に対応し、これは 2 つのカテゴリの分類問題です。実験の手順は次のとおりです。
- 特性属性と分割を決定します。指定されたデータベースを参照して、分割された特性属性を見つけます。
- トレーニング サンプルを取得します。つまり、指定された AllElectronics 顧客データベース クラスによってマークされたトレーニング サンプル セット
(タプル)です。 - トレーニング サンプル内の各カテゴリの事前確率を計算します: P(Ci)、i=1、2;
- トレーニング サンプルのクラス条件付き確率を計算します。特徴 (属性) ベクトルを X とし、クラス条件付き
確率 P(X|Ci)、i=1、2 を計算するプログラムを作成します。 - 分類子を使用して分類します。
3. プログラムブロック図
4. 実験サンプル
データ.txt
5. 実験コード
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2021 #
# @Time : 2022/5/30 21:26
# @Author : Yang Haoyuan
# @Email : [email protected]
# @File : Exp4.py
# @Software: PyCharm
import pandas as pd
import numpy as np
from sklearn.model_selection import KFold
import argparse
parser = argparse.ArgumentParser(description='Exp4')
parser.add_argument('--mode', type=str, choices=["KFold", "train", "test"])
parser.add_argument('--k', type=int, default=7)
parser.add_argument('--AGE', type=str, choices=["youth", "middle_aged", "senior"])
parser.add_argument('--INCOME', type=str, choices=["high", "medium", "low"])
parser.add_argument('--STUDENT', type=str, choices=["yes", "no"])
parser.add_argument('--CREDIT', type=str, choices=["excellent", "fair"], default="fair")
parser.set_defaults(augment=True)
args = parser.parse_args()
print(args)
# 载入数据集
def loadDataset(filename):
dataSet = []
with open(filename, 'r') as file_to_read:
while True:
lines = file_to_read.readline() # 整行读取数据
if not lines:
break
p_tmp = [str(i) for i in lines.split(sep="\t")]
p_tmp[len(p_tmp) - 1] = p_tmp[len(p_tmp) - 1].strip("\n")
dataSet.append(p_tmp)
return pd.DataFrame(dataSet, columns=["AGE", "INCOME", "STUDENT", "CREDIT", "BUY"])
# 计算总样本数和各类数量
def count_total(data):
count = {
}
group_df = data.groupby(["BUY"])
count["yes"] = group_df.size()["yes"]
count["no"] = group_df.size()["no"]
total = count["yes"] + count["no"]
return count, total
# 计算各类概率
def cal_base_rates(categories, total):
rates = {
}
for label in categories:
priori_prob = categories[label] / total
rates[label] = priori_prob
return rates
# 计算各类条件概率
def f_prob(data, count):
likelihood = {
'yes': {
}, 'no': {
}}
# 根据AGE(youth, middle_aged, senior)和BUY(yes, no)统计概率
df_group = data.groupby(['AGE', 'BUY'])
try:
c = df_group.size()["youth", "yes"]
except:
c = 0
likelihood['yes']['youth'] = c / count['yes']
try:
c = df_group.size()["youth", "no"]
except:
c = 0
likelihood['no']['youth'] = c / count['no']
try:
c = df_group.size()["middle_aged", "yes"]
except:
c = 0
likelihood['yes']['middle_aged'] = c / count['yes']
try:
c = df_group.size()["middle_aged", "no"]
except:
c = 0
likelihood['no']['middle_aged'] = c / count['no']
try:
c = df_group.size()["senior", "yes"]
except:
c = 0
likelihood['yes']['senior'] = c / count['yes']
try:
c = df_group.size()["senior", "no"]
except:
c = 0
likelihood['no']['senior'] = c / count['no']
# 根据INCOME(high, medium, low)和BUY(yes, no)统计概率
df_group = data.groupby(['INCOME', 'BUY'])
try:
c = df_group.size()["high", "yes"]
except:
c = 0
likelihood['yes']['high'] = c / count['yes']
try:
c = df_group.size()["high", "no"]
except:
c = 0
likelihood['no']['high'] = c / count['no']
try:
c = df_group.size()["medium", "yes"]
except:
c = 0
likelihood['yes']['medium'] = c / count['yes']
try:
c = df_group.size()["medium", "no"]
except:
c = 0
likelihood['no']['medium'] = c / count['no']
try:
c = df_group.size()["low", "yes"]
except:
c = 0
likelihood['yes']['low'] = c / count['yes']
try:
c = df_group.size()["low", "no"]
except:
c = 0
likelihood['no']['low'] = c / count['no']
# 根据STUDENT(yes, no)和BUY(yes, no)统计概率
df_group = data.groupby(['STUDENT', 'BUY'])
try:
c = df_group.size()["yes", "yes"]
except:
c = 0
likelihood['yes']['yes'] = c / count['yes']
try:
c = df_group.size()["yes", "no"]
except:
c = 0
likelihood['no']['yes'] = c / count['no']
try:
c = df_group.size()["no", "yes"]
except:
c = 0
likelihood['yes']['no'] = c / count['yes']
try:
c = df_group.size()["no", "no"]
except:
c = 0
likelihood['no']['no'] = c / count['no']
# 根据CREDIT(excellent, fair)和BUY(yes, no)统计概率
df_group = data.groupby(['CREDIT', 'BUY'])
try:
c = df_group.size()["excellent", "yes"]
except:
c = 0
likelihood['yes']['excellent'] = c / count['yes']
try:
c = df_group.size()["excellent", "no"]
except:
c = 0
likelihood['no']['excellent'] = c / count['no']
try:
c = df_group.size()["fair", "yes"]
except:
c = 0
likelihood['yes']['fair'] = c / count['yes']
try:
c = df_group.size()["fair", "no"]
except:
c = 0
likelihood['no']['fair'] = c / count['no']
return likelihood
# 训练
def train(train_data):
# 获取各类数量和训练样本总数
count, total = count_total(train_data)
# 获取先验概率
priori_prob = cal_base_rates(count, total)
# 保存先验概率
np.save("priori_prob.npy", priori_prob)
# 获取各特征的条件概率
feature_prob = f_prob(train_data, count)
# 保存条件概率
np.save("feature_prob.npy", feature_prob)
print("训练完成")
# 分类器
def NaiveBayesClassifier(AGE=None, INCOME=None, STUDENT=None, CREDIT=None):
res = {
}
priori_prob = np.load('priori_prob.npy', allow_pickle=True).item()
feature_prob = np.load('feature_prob.npy', allow_pickle=True).item()
# 根据特征计算各类的概率
for label in ['yes', 'no']:
prob = priori_prob[label]
prob *= feature_prob[label][AGE] * feature_prob[label][INCOME] * feature_prob[label][STUDENT] \
* feature_prob[label][CREDIT]
res[label] = prob
print("预测概率:", res)
# 选择概率最高的类作为分类结果
res = sorted(res.items(), key=lambda kv: kv[1], reverse=True)
return res[0][0]
# 测试
def test(test_data):
correct = 0
for idx, row in test_data.iterrows():
prob = NaiveBayesClassifier(row["AGE"], row["INCOME"], row["STUDENT"], row["CREDIT"])
if prob == row["BUY"]:
correct = correct + 1
return correct / test_data.shape[0]
# 启用k-折交叉验证
def KFoldEnabled():
kf = KFold(n_splits=args.k)
data_set = loadDataset("date.txt")
corr = 0
for train_idx, test_idx in kf.split(data_set):
train_data = data_set.loc[train_idx]
test_data = data_set.loc[test_idx]
train(train_data)
corr = corr + test(test_data)
print("k折交叉验证正确率: ", corr / 7)
if __name__ == '__main__':
if args.mode == "KFold":
KFoldEnabled()
if args.mode == "train":
train_data = loadDataset("date.txt")
train(train_data)
if args.mode == "test":
'''priori_prob = np.load('priori_prob.npy', allow_pickle=True).item()
print("先验概率: ", priori_prob)
feature_prob = np.load('feature_prob.npy', allow_pickle=True).item()
print("类条件概率: ", feature_prob)'''
ret = NaiveBayesClassifier(args.AGE, args.INCOME, args.STUDENT, args.CREDIT)
print("预测结果: ", ret)
4. 実験結果
トレーニングとテストに k 分割交差検証を使用します。k=7
トレーニング モデル
モデル予測
5. 実験分析
この実験では主に Naive Bayes 分類アルゴリズムを実装します。
ベイジアン法はベイズの原理に基づいており、確率と統計の知識を使用してサンプル データセットを分類します。確固たる数学的基礎があるため、ベイジアン分類アルゴリズムの誤検知率は非常に低くなります。ベイジアン法の特徴は、事前確率と事後確率を組み合わせることで、事前確率のみを使用することによる主観的なバイアスや、サンプル情報のみを使用することによる過適合現象を回避することです。ベイジアン分類アルゴリズムは、データセットが大きい場合に高い精度を示し、アルゴリズム自体は比較的単純です。
ナイーブ ベイジアン アルゴリズムは、ベイジアン アルゴリズムに基づいて簡略化されています。つまり、ターゲット値が与えられた場合、属性は条件付きで互いに独立していると想定されます。つまり、判定結果に対する割合が大きい属性変数もあれば、判定結果に対する割合が小さい属性変数も存在しない。この単純化により、ベイズ分類アルゴリズムの分類効果はある程度減少しますが、実際のアプリケーション シナリオでは、ベイズ手法の複雑さが大幅に単純化されます。
これにより、ナイーブ ベイズ分類の堅牢性が強化されますが、実際には、属性間の独立性の仮定により、分類パフォーマンスも制限されます。
この実験データにはトレーニング セットと検証セットの区別がありません。このデータ セットに対する単純ベイズ分類器のパフォーマンスを検証するために、K 分割交差検証アルゴリズムを使用しました。最終的な分類精度はわずか 50% でしたが、これはデータ セットの数が少なく、単純なベイズ分類器がこのタスクに関して十分にトレーニングされていなかったためと考えられます。
分類を適用するときにパラメーターを直接読み取り、分類を実行できるように、トレーニング データを .npy ファイルとして保存します。