数据挖掘总结:
第一章:
数据挖掘KDD
步骤:
- 数据清理: (消除噪声和删除不一致的数据)
- 数据集成(多种数据源可以组合在一起)
- 数据选择(从数据库中提取与分析任务相关的数据)
- 数据变换(数据变换或统一成适合挖掘的形式)
- 数据挖掘(核心步骤,使用智能方法提取数据模式)
- 模式评估(根据某种兴趣度量识别提供知识的真正有趣的模式)
- 知识表示(使用可视化和知识表示技术,向用户提供挖掘的知识)
数据仓库(数据立方体):是一个从多个数据源收集的信息存储库,存放在一致的模式下,并且通常驻留在单个站点上。
文本数据库的分类:
- 无结构类型、半结构类型、结构类型
研究任务:
- 关联规则,分类回归,聚类,离群点分析
数据库系统研究关注为单位和最终用户创建、维护和使用数据库。
数据仓库集成来自多种数据源和各个时间段的数据。
第二章:
- 数据集由数据对象组成。数据行对应数据对象,列对应属性。
属性:
- 标称属性 :属性值是一些符号或者事物的名称,属于哪一类
- 二元属性 :只有两个状态例如:是或者不是,有或者没有
- 序数属性:其可能的值之间具有有意义的序或者秩评定,例如评定等级
- 数值属性::定量的且用具体数值表示
对于数据的描述信息:
中心趋势度量
- 均值、中位数、众数、中列数
数据的散布
- 极差、四分位数极差、五数概括、盒图、变异系数
数据可视化
- 分位数图、分位数-分位数图、直方图、散点图、词云图
数据度量:
- 相似性、相异性、邻近性
空间距离:
- 曼哈顿距离、欧氏距离、切比雪夫距离、切比雪夫距离、绝对值距离,闵考夫斯基距离
数据规整:
- 数据归一化、数据标准化
from sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
第三章:
数据预处理:
数据清理
- 填充缺失值,识别/去除离群点,光滑噪音,并纠正数据中的不一致
数据集成:
- 多个数据库,数据立方体或文件的集成
数据规约:
-
得到数据的归约表示,它小得多,但产生相同或类似的分析结果:维度规约、数值
规约、数据压缩
缺失值处理,离散点处理
重复值处理、相关性分析
主要成分分析(PCA降维),奇异值分解
第四章:
数据仓库:
数据仓库是一个面向主题的、集成的、随时间而变化的、不容易丢失的数据集合,支持管理部门的决策过程
数据仓库特征:面向主题、数据集成、随时间而变化、数据不易丢失
数据库的主要任务:联机事务处理(OLTP)和增删改查(CURD).
数据仓库的主要任务:联机分析处理(OLAP),数据分析和决策支持.
数据仓库的三层架构:
- 底层:数据仓库的数据库服务器
- 中间层:OLAP服务器
- 前端客户工具层
OLAP的优点:
数据展现方式
基于多维模型的数据组织让数据的展示更加直观,可以从多个角度多个层面去发现事物的不同特性,而OLAP正是将这种寻常的思维模型应用到了数据分析上。
查询效率
多维模型的建立是基于对OLAP操作的优化基础上的,比如基于各个维的索引、对于一些常用查询所建的视图等,这些优化使得对百万千万甚至上亿数量级的运算变得得心应手。
分析的灵活性
多维数据模型可以从不同的角度和层面来观察数据,同时各类OLAP操作对数据进行聚合、细分和选取,可以从不同角度不同层面对数据进行细分和汇总,满足不同分析的需求。
数据立方体是一种多维数据分析工具,提供了对数据仓库中的数据进行实时分析的能力。
频繁模式挖掘:
关联规则:
关联规则反映一个事物与其他事物之间的相互依存性和关联性。若两个或多个事物之间存在一定的关联关系,则其中一个事物就能够通过其他事物预测到。
应用
购物篮数据分析, 交叉销售, 顾客购买习惯分析, Web 日志 (click stream) 分析等。
频繁模式: 频繁出现在数据集中的模式。
项(item)
- 每种商品为项
项集(itemset)
- 项集:项的集合
- k-项集:含有k个项的项集
- 所有项的集合 I={I1,I2,I3,I4,I5}
假如我们把一次购物当成一个购物篮,所购买的每一个东西叫做项,那么项集叫做项的集合,k项集就是还有k个项的项集(就是你买了k键物品),所有项的集合={一项集,二项集,…,n项集},这样是不是就比较好理解了呢。
Tid Milk Nuts Eggs Beer Coffe Diaper
10 0 1 0 1 0 1
20 0 0 0 1 1 1
30 0 1 1 1 0 1
40 1 0 1 0 0 0
50 1 1 0 0 1 1
1频繁项集:{Beer}(支持度0.6), {Nuts} (支持度0.6), {Diaper}:(支持度0.8), {Eggs} (支持度0.6), -----竖着看
2频繁项集:{Beer, Diaper}(支持度0.6)
支持度
数据集D中包含项集A的事务中同时包含另一个项集B的比例,其中A ∩ 𝐵 = ∅ 。一个发生,同时另一个也发生。
频繁项集挖掘:
超集:若一个集合S**2中的每一个元素都在集合S**1中,且集合S1 中可能包含S2中没有的元素,则集合S**1就是S**2的一个超集。S**1是S**2 的超集,则S2是S1的真子集,反之亦然。支持度:0.3支持度:大于或等于0.3。
S
1
属于
S
2
S1属于S2
S1属于S2
现在有项集S1 ={b,c} ,那么它就是{b},{c}的超集。
S1也是*{a,b,c}*等的真子集
Apriori算法:
频繁项集的所有非空子集也必须是频繁的,就是如果三个都能同时发生,那么两个也一定发生。如果 {beer, diaper, nuts} 是频繁的, {beer, diaper}也是。
**非频繁项集的超集(真子集)一定是非频繁的。**可以理解为一个事件不发生,那么这个事件和另一个事件同时发生的概率一定小于一个事件发生的概率,如果 {beer, diaper} 是非频繁的, 也是{beer, diaper, nuts}非频繁的。支持度:0.1,支持度:小于或等于0.1.
不相同元素只有两个的k-1频繁项集(只有一个不相同)才可以生成一个k待频繁项集.
{I1,I3}+ {I1,I4}==>>{I1, I3,I4} (只有两个元素不相同的集合)
Apriori
算法由连接和剪枝两个步骤组成。
import pandas as pd
import numpy as np
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import association_rules
from mlxtend.frequent_patterns import apriori
from mlxtend.frequent_patterns import fpgrowth
pd.set_option('display.max_columns', None) # 显示所有列
pd.set_option('display.max_rows', None) # 显示所有行
column_names = ['a' + str(i) for i in range(1, 24)]
print(column_names)
# 读取文件
df = pd.read_csv('./data/mushroom.dat', encoding='utf-8', sep=' ', names=column_names, index_col=False)
# 查看前几行数据
print(df.head())
print('------------------------------')
# 查看每列是否存在缺失值
# print(df.isnull().sum())
# 删除存在确实值的行
df.dropna(inplace=True)
print(df.head())
# 刷选毒蘑菇
df2 = df[df['a1'] == 2]
df2.reset_index(drop=True)
print('------------------------------')
# print(df2.head())
# 转化为2维度数组
df3 = df2.values.tolist()
print(df3)
# aprior
print('------------------------------')
te = TransactionEncoder() # 生成模型对象
te_ary = te.fit(df3).transform(df3)
# te.columns_就是出现的所有字段列名 te_df构成一个新的dafaframe类型
te_df = pd.DataFrame(te_ary, columns=te.columns_)
ap_result = apriori(te_df, min_support=0.4, use_colnames=True)
print(ap_result)
print(ap_result['itemsets'])
# FP 树算法
fp_result = fpgrowth(te_df, min_support=0.4, use_colnames=True)
print(fp_result)
print(fp_result['itemsets'])
# 关联规则生成
res = association_rules(ap_result, metric='confidence', min_threshold=0.4, support_only=False)
print(res)
模型评估度量:
- 全置信度
- 最大置信度
- Kulczynski
- 余弦
分类:
分类任务的两个极端:模型过拟合,模型欠拟合
提高分类任务精度的方法:特征选择,特征工程,交叉验证,网格搜索,模型调优
决策树:
决策树是一种常用的机器学习算法,可用于分类和回归任务。它通过从数据中学习一系列的决策规则来构建一个树形结构,从而对新样本进行预测或估计。
属性选择度量:
-
信息增益
- 偏向于多值属性
增益率
- 倾向于不平衡的划分,其中一个分区比其他分区小得多
基尼指数
-
偏向于多值属性
-
当类的数量很大时会有困难
-
倾向于导致相等大小的分区和纯度
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
import pandas as pd
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import export_graphviz
import graphviz
df = pd.read_csv('./data/lenses.txt', sep='\t')
# 数据探索
print(df.head())
# 缺失值处理
is_column_missing = df.isnull().any(axis=0)
# print(is_column_missing)
# 查看每一行是否存在缺失值
is_row_missing = df.isnull().any(axis=1)
# print(is_row_missing)
# 分离特征和目标变量
X = df.drop('eye_types', axis=1)
y = df['eye_types']
# 使用独热编码进行特征向量化
# X.to_dict() 是将每一列映射为数字
vectorizer = DictVectorizer(sparse=False)
X_encoded = vectorizer.fit_transform(X.to_dict(orient='records'))
print(X_encoded,X_encoded.shape)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_encoded, y, test_size=1 / 6, random_state=42)
# 创建决策树分类器
clf = DecisionTreeClassifier(criterion="entropy", random_state=30, splitter="best")
# # 在训练集上拟合模型
clf.fit(X_train, y_train)
# # 评估方法一
# # 在测试集上进行预测 准确率
y_pred = clf.predict(X_test)
score = clf.score(X_test, y_test)
# # 评估方法二
# # 计算测试精度
accuracy = accuracy_score(y_test, y_pred)
from sklearn.metrics import precision_score, recall_score, f1_score
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
# 打印测试精度
print('测试精度:', accuracy)
print( f"模型的测试分类准确率为{score:.2%}")
# 生成Graphviz格式的决策树图形
dot_data = export_graphviz(clf, feature_names=vectorizer.feature_names_, class_names=clf.classes_, filled=True,
rounded=True)
# 渲染决策树图形
graph = graphviz.Source(dot_data)
# # 保存决策树图形为PDF文件
graph.render('./show/decision_tree')
贝叶斯:
在正确辅助信息的指引下,后验概率比先验概率对分类决策更有效!
from sklearn.naive_bayes import GaussianNB
import numpy as np
# 准备训练数据和标签
X_train = np.array([[1, 2], [3, 4], [5, 6]])
y_train = np.array([0, 1, 0])
# 创建 GaussianNB 对象
gnb = GaussianNB()
# 拟合模型
gnb.fit(X_train, y_train)
# 预测新样本
X_new = np.array([[2, 3], [4, 5]])
y_pred = gnb.predict(X_new)
print(y_pred)
K近邻:
-
核心思想:如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性个类别,并具有这个类别上样本的特性。
-
距离越小则相似度越大
常用的空间距离:闵可夫斯基距离、欧氏距离、曼哈顿距离
量纲处理:归一化、标准化
K的选择:交叉验证
KNN
优缺点对比:
优点:
- 简单直观,训练非常快,易于实现;
- 特别适合多分类问题;
- 训练数据无限和足够大的K,K-NN方法效果会相当好!
缺点:
- 对噪声敏感(小K);
- 即使在测试时间时,也需要存储所有训练数据;
- 查询时间慢:每个查询𝑂(𝑛𝑑)复杂度;
- 在高维度上,距离的概念是违反直觉的!
- 高维空间表现不佳(维度诅咒)
交叉验证:
import pandas as pd
df=pd.read_csv('./data/datingTestSet.txt',sep='\t',header=None)
print(df.head())
print("------------------------------")
# 1. 数据探索
# 查看每一组分别有多少人
value_counts = df[3].value_counts()
# 需要将目标变量映射为数值类型
maplist=value_counts.index.tolist()
# 建立映射关系
mapping = {value: index for index, value in enumerate(maplist)}
print(mapping)
# df[3] = df[3].map(mapping)
# print("映射之后的数据字段为-------------------")
# print(df.head())
# 2.数据预处理
X = df.iloc[:, :-1] # Features
y = df.iloc[:, -1] # Target variabl
from sklearn.preprocessing import MinMaxScaler
# 创建一个MinMaxScaler对象
scaler = MinMaxScaler()
# 对特征矩阵X进行归一化处理
normalized_X = scaler.fit_transform(X)
print(normalized_X)
from sklearn.model_selection import cross_val_score
from sklearn.neighbors import KNeighborsClassifier
# 3. 数据建模
k_values = [1, 3, 5, 7, 9] # 可选的k值
best_accuracy = 0 # 最优准确率
best_k = None # 最优的k值
for k in k_values:
# 创建KNN分类器
knn = KNeighborsClassifier(n_neighbors=k)
# 十折交叉验证,计算平均准确率
scores = cross_val_score(knn, normalized_X, y, cv=10)
accuracy = scores.mean()
# 更新最优准确率和k值
if accuracy > best_accuracy:
best_accuracy = accuracy
best_k = k
print("最优的k值:", best_k)
print("最优准确率:", best_accuracy)
网格搜索:
import pandas as pd
import numpy as np
from sklearn.model_selection import GridSearchCV
from sklearn import preprocessing
from sklearn.neighbors import KNeighborsClassifier
df = pd.read_csv("./data/datingTestSet.txt",sep="\t",header=None)
print(df.head())
X = preprocessing.MinMaxScaler().fit_transform(df.iloc[:,:-1])
Y = df.iloc[:,-1] # 获取因变量
param_grid = {'n_neighbors' :np.arange(1, 11, 1) } #定义网格参数
clf = KNeighborsClassifier()
GS_model = GridSearchCV(clf, param_grid, cv=10) # GS_model 就是获得的最优参数
GS_model.fit(X, Y) # 训练
print(f'模型的最优参数最优配置为{GS_model.best_params_},且训练精度为{GS_model.best_score_:.3f}')
感知机:
感知机(perceptron)是二分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别。
模型优化:梯度下降法
单层感知机:
import matplotlib.pyplot as plt
from sklearn import datasets, tree
from sklearn.model_selection import cross_val_score
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import Perceptron
from sklearn.metrics import precision_score, recall_score, f1_score,accuracy_score
import numpy as np
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来显示中文,不然会乱码
plt.rcParams['font.family'] = 'Microsoft YaHei' # 或者 'Source Han Sans'
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 定义数据集的URL
file = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
# 定义列名
names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'class']
# 使用Pandas的read_csv函数加载数据集
df = pd.read_csv(file, names=names)
# 选择 sepal_length 和 petal_length 列数据作为目标数据
target_data = df[['sepal_length', 'petal_length']]
# 选择类别不是'Iris-virginica'的数据,并将其类别重命名为+1和-1
filtered_data = df[df['class'] != 'Iris-virginica'].copy()
filtered_data['class'] = filtered_data['class'].apply(lambda x: 1 if x == 'Iris-versicolor' else -1)
print(filtered_data)
# 根据类别创建颜色映射字典
colors = {1: 'red', -1: 'blue'}
# 获取 petal_length 和 sepal_length 列的数据
petal_length = filtered_data['petal_length']
sepal_length = filtered_data['sepal_length']
# 根据类别绘制散点图
plt.figure(figsize=(10, 6))
for label in colors:
plt.scatter(sepal_length[filtered_data['class'] == label],
petal_length[filtered_data['class'] == label],
c=colors[label],
label=f'Class {label}')
plt.xlabel('sepal_length')
plt.ylabel('petal_length')
plt.title('Petal Length vs Sepal Length (Scatter Plot)')
plt.legend(loc='best')
plt.show()
# 随机打乱数据集
shuffled_data = filtered_data.sample(frac=1, random_state=42).reset_index(drop=True)
# 划分训练集和测试集
X = shuffled_data[['sepal_length', 'petal_length']]
y = shuffled_data['class']
X_train, X_test = X[:80], X[80:100]
y_train, y_test = y[:80], y[80:100]
# 训练感知机模型
perceptron = Perceptron()
perceptron.fit(X_train, y_train)
# 计算测试精度
y_pred = perceptron.predict(X_test)
# 使用预测结果和真实标签计算模型精度
accuracy = accuracy_score(y_test, y_pred)
# 打印模型精度
print("测试精度 (使用predict()):", accuracy)
# 使用perceptron.score()来计算模型精度
accuracy_score = perceptron.score(X_test, y_test)
print("测试精度 (使用score()):", accuracy_score)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
多层感知机:
import pandas as pd
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import cross_val_score
import numpy as np
# 数据集的链接
url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
# 列名
column_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'class']
# 使用 pandas 加载数据集
df = pd.read_csv(url, names=column_names)
# 查看数据集的前几行
print(df.head())
# 数据准备
X = df.drop('class', axis=1) # 特征
y = df['class'] # 目标变量
print(X)
# 构建多层感知机模型
mlp = MLPClassifier(max_iter=1000)
# 定义参数网格
param_grid = {
'hidden_layer_sizes':np.arange(30, 91, 5),
'activation': ["identity", "logistic", "tanh", "relu"],
}
# 使用GridSearchCV进行参数搜索
grid_search = GridSearchCV(mlp, param_grid, cv=3)
grid_search.fit(X, y)
# 打印最佳参数配置
print("最佳参数配置: ", grid_search.best_params_)
# 执行交叉验证来评估模型性能
best_mlp = grid_search.best_estimator_
cv_scores = cross_val_score(best_mlp, X, y, cv=3)
print("交叉验证得分: ", cv_scores)
print("平均得分: ", cv_scores.mean())
聚类:
Kmeans:
import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
import os
os.environ['OMP_NUM_THREADS'] = '4'
# 读取数据
data = pd.read_excel('./data/consumption_data.xls')
# 数据探索与数据预处理
print("查看前几条数据")
print(data)
# 缺失值
print("每一列缺失值查看:")
# 查看缺失值
missing_values = data.isnull().sum()
print(missing_values)
# 查看缺失行
print("查看缺失行:")
missing_rows = data[data.isnull().any(axis=1)]
print(missing_rows)
# 删除缺失值所在的行
data = data.dropna(axis=0)
# 打印删除缺失值后的数据
print(data)
# 数据预处理和特征选择
X = data[['R', 'F', 'M']] # 选择特征列
# 特征标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 设置聚类的簇数
n_clusters = 3
# 创建KMeans对象并进行聚类
kmeans = KMeans(n_clusters=n_clusters,n_init=10)
kmeans.fit(X_scaled)
# 获取聚类结果标签
labels = kmeans.labels_
# 将聚类结果添加到原始数据中
data['Cluster'] = labels
print("聚类中心------")
print(kmeans.cluster_centers_)
# 分别提取不同群体的数据
cluster0 = data[data['Cluster'] == 0]
cluster1 = data[data['Cluster'] == 1]
cluster2 = data[data['Cluster'] == 2]
# 单图展示
# 获取属性列的名称
attribute_columns = ['R', 'F', 'M'] # 假设属性列为'R', 'F', 'M'
# 创建一个图像
fig, axes = plt.subplots(len(attribute_columns), 1, figsize=(8, 12))
# 绘制概率密度函数图像
for i, attribute in enumerate(attribute_columns):
cluster0[attribute].plot(kind='kde', label='Cluster 0', ax=axes[i])
cluster1[attribute].plot(kind='kde', label='Cluster 1', ax=axes[i])
cluster2[attribute].plot(kind='kde', label='Cluster 2', ax=axes[i])
axes[i].set_xlabel(attribute)
axes[i].set_ylabel('Density')
axes[i].legend()
plt.tight_layout()
# plt.savefig(r'./img/2_mode.png')
plt.show()
模型评估:
import pandas as pd
from sklearn.linear_model import Perceptron
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import roc_curve, roc_auc_score, auc
import matplotlib.pyplot as plt
# 读取数据集
data = pd.read_csv('./data/balance.dat')
print("数据类型查看:")
print(data.head())
# 去除列名中的空格
data.columns = data.columns.str.replace(' ', '')
class_counts = data['Class'].value_counts()
data['Class'] = data['Class'].astype(str)
unique_class_values = data['Class'].unique()
print("查看都有那些值", unique_class_values)
# 将类别属性"class"取值为"L"的类定义为正例,取值为"R"的类定义为负类
data['Class'] = data['Class'].str.strip().map({'L': 1, 'R': -1, 'B': 0})
data = data[(data['Class'] == 1) | (data['Class'] == -1)]
# 打印前几行数据以验证处理结果
print("处理后的数据:")
print(data.head())
# 准备特征和目标变量
X = data.drop(columns=['Class'])
y = data['Class']
# 数据建模与模型选择
# 构建不同模型的分类器
classifiers = {
'Naive Bayes': GaussianNB(),
'Decision Tree': DecisionTreeClassifier(),
'K-Nearest Neighbors': KNeighborsClassifier(),
'Perceptron': Perceptron()
}
# 使用十折交叉验证计算各算法的召回率、精度和F度量
results = {}
for name, clf in classifiers.items():
recall_scores = cross_val_score(clf, X, y, cv=10, scoring='recall') # 召回率
precision_scores = cross_val_score(clf, X, y, cv=10, scoring='precision')
f1_scores = cross_val_score(clf, X, y, cv=10, scoring='f1')
results[name] = {
'Recall': recall_scores.mean(),
'Precision': precision_scores.mean(),
'F-Measure': f1_scores.mean()
}
print(results)
# 打印各算法的性能指标
for name, metrics in results.items():
print(f'Algorithm: {name}')
print(f'Recall: {metrics["Recall"]:.2f}')
print(f'Precision: {metrics["Precision"]:.2f}')
print(f'F-Measure: {metrics["F-Measure"]:.2f}')
print()
# 选择最优的分类算法(以F度量为准则)
best_algorithm = max(results, key=lambda x: results[x]['F-Measure'])
print(f'Best Algorithm: {best_algorithm}')
# ROC 图制作与 AUC 取值计算
# 将数据集分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建决策树分类器
dt_classifier = DecisionTreeClassifier()
# 创建朴素贝叶斯分类器
nb_classifier = GaussianNB()
# 训练模型
dt_classifier.fit(X_train, y_train)
nb_classifier.fit(X_train, y_train)
# 预测概率
y_prob_dt = dt_classifier.predict_proba(X_test)[:, 1]
y_prob_nb = nb_classifier.predict_proba(X_test)[:, 1]
# 计算 ROC 曲线
fpr_dt, tpr_dt, _ = roc_curve(y_test, y_prob_dt)
fpr_nb, tpr_nb, _ = roc_curve(y_test, y_prob_nb)
# 计算 AUC 值
auc_dt = auc(fpr_dt, tpr_dt)
auc_nb = auc(fpr_nb, tpr_nb)
# 绘制 ROC 曲线
plt.figure(figsize=(8, 6))
plt.plot(fpr_dt, tpr_dt, label=f'Decision Tree (AUC = {auc_dt:.2f})')
plt.plot(fpr_nb, tpr_nb, label=f'Naive Bayes (AUC = {auc_nb:.2f})')
plt.plot([0, 1], [0, 1], linestyle='--', color='gray', label='Random')
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('ROC Curve')
plt.legend()
plt.show()
# 打印 AUC 值
print(f'Decision Tree AUC: {auc_dt:.2f}')
print(f'Naive Bayes AUC: {auc_nb:.2f}')