当前位置: 首页 > news >正文

机器学习笔记3

五 sklearn机器学习概述

获取数据、数据处理、特征工程后,就可以交给预估器进行机器学习,流程和常用API如下。

1.实例化预估器(估计器)对象(estimator), 预估器对象很多,都是estimator的子类
    (1)用于分类的预估器
        sklearn.neighbors.KNeighborsClassifier k-近邻
        sklearn.naive_bayes.MultinomialNB 贝叶斯
        sklearn.linear_model.LogisticRegressioon 逻辑回归
        sklearn.tree.DecisionTreeClassifier 决策树
        sklearn.ensemble.RandomForestClassifier 随机森林
    (2)用于回归的预估器
        sklearn.linear_model.LinearRegression线性回归
        sklearn.linear_model.Ridge岭回归
    (3)用于无监督学习的预估器
        sklearn.cluster.KMeans 聚类
2.进行训练,训练结束后生成模型
    estimator.fit(x_train, y_train)
3.模型评估
    (1)方式1,直接对比
        y_predict = estimator.predict(x_test)
        y_test == y_predict
    (2)方式2, 计算准确率
        accuracy = estimator.score(x_test, y_test)
4.使用模型(预测)
y_predict = estimator.predict(x_true)

六 KNN算法-分类

1 样本距离判断

    明可夫斯基距离欧式距离,明可夫斯基距离的特殊情况 曼哈顿距离,明可夫斯基距离的特殊情况 

两个样本的距离公式可以通过如下公式进行计算,又称为欧式距离。

(1)欧式距离

(2)曼哈顿距离

2 KNN 算法原理

K-近邻算法(K-Nearest Neighbors,简称KNN),根据K个邻居样本的类别来判断当前样本的类别;

如果一个样本在特征空间中的k个最相似(最邻近)样本中的大多数属于某个类别,则该类本也属于这个类别

比如: 有10000个样本,选出7个到样本A的距离最近的,然后这7个样本中假设:类别1有2个,类别2有3个,类别3有2个.那么就认为A样本属于类别2,因为它的7个邻居中 类别2最多(近朱者赤近墨者黑)

4. 举例

使用KNN算法预测《唐人街探案》电影属于哪种类型?分别计算每个电影和预测电影的距离然后求解:

3 KNN缺点

对于大规模数据集,计算量大,因为需要计算测试样本与所有训练样本的距离。

对于高维数据,距离度量可能变得不那么有意义,这就是所谓的“维度灾难”

需要选择合适的k值和距离度量,这可能需要一些实验和调整

4 API

class sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, algorithm='auto')
参数:                                            
(1)n_neighbors:
        int, default=5, 默认情况下用于kneighbors查询的近邻数,就是K
(2)algorithm:
    {‘auto’, ‘ball_tree’, ‘kd_tree’, ‘brute’}, default=’auto’。找到近邻的方式,注意不是计算距离      的方式,与机器学习算法没有什么关系,开发中请使用默认值'auto'
方法:
(1) fit(x, y)
       使用X作为训练数据和y作为目标数据  
(2) predict(X) 预测提供的数据,得到预测数据                                                                            

5 sklearn 实现KNN示例

用KNN算法对鸢尾花进行分类

# 用KNN算法对鸢尾花进行分类
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier# 1)获取数据
iris = load_iris()
​
# 只有4个特征, 150个样本
print(iris.data.shape) #(150,4)
# 4个特征的描述 ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
print(iris.feature_names)
​
# 150个目标,对应150个样本的类别
print(iris.target.shape) #(150,)
# 目标值只有0 1 2这三种值,说明150个样本属于三类中的其中一种
print(iris.target) #[0 0 0...1 1 1 ...2 2 2]
# 目标值三种值代表的三种类型的描述。
print(iris.target_names) #['setosa' 'versicolor' 'virginica']
​
# 2)划分数据集
​
# x_train训练特征,y_train训练目标, x_test测试特征,y_test测试目标
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)
# print(x_train.shape, x_test.shape, y_train.shape, y_test.shape) #(112, 4) (38, 4) (112,) (38,)
​
# 3)特征工程:标准化, 只有4个特征
transfer = StandardScaler()
# 对训练特征做标准化, 对测试特征做相同的标准化,因为fit_transform中已经有fit进行计算了,所以对x_test只需要做transform了
# 训练用的什么数据,模式就只能识别什么样的数据。
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
​
​
# 4)KNN算法预估器, k=7表示找7个邻近来判断自身类型. 
estimator = KNeighborsClassifier(n_neighbors=7)
estimator.fit(x_train, y_train)#该步骤就是estimator根据训练特征和训练目标在自己学习,让它自己变聪敏
# 5)模型评估  测试一下聪敏的estimator能力
# 方法1:直接比对真实值和预测值, 
y_predict = estimator.predict(x_test) #y_predict预测的目标结果
print("y_predict:\n", y_predict)
print("直接比对真实值和预测值:\n", y_test == y_predict)
​
# 方法2:计算准确率, 
score = estimator.score(x_test, y_test)
print("准确率为:\n", score) #0.9473684210526315

输出:

(150, 4)
['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
(150,)
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
2 2]
['setosa' 'versicolor' 'virginica']
y_predict:
[0 2 1 2 1 1 1 1 1 0 2 1 2 2 0 2 1 1 1 1 0 2 0 1 2 0 2 2 2 2 0 0 1 1 1 0 0
0]
直接比对真实值和预测值:
[ True  True  True  True  True  True  True False  True  True  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  True]
准确率为:
0.9473684210526315

6 模型保存与加载

import joblib
# 保存模型
joblib.dump(estimator, "my_ridge.pkl")
# 加载模型
estimator = joblib.load("my_ridge.pkl")
#使用模型预测
y_test=estimator.predict([[0.4,0.2,0.4,0.7]])
print(y_test)

七 模型选择与调优

1 交叉验证

(1) 保留交叉验证HoldOut

HoldOut Cross-validation(Train-Test Split)

在这种交叉验证技术中,整个数据集被随机地划分为训练集和验证集。根据经验法则,整个数据集的近70%被用作训练集,其余30%被用作验证集。也就是我们最常使用的,直接划分数据集的方法。

优点:很简单很容易执行。

缺点1:不适用于不平衡的数据集。假设我们有一个不平衡的数据集,有0类和1类。假设80%的数据属于 “0 “类,其余20%的数据属于 “1 “类。这种情况下,训练集的大小为80%,测试数据的大小为数据集的20%。可能发生的情况是,所有80%的 “0 “类数据都在训练集中,而所有 “1 “类数据都在测试集中。因此,我们的模型将不能很好地概括我们的测试数据,因为它之前没有见过 “1 “类的数据。

缺点2:一大块数据被剥夺了训练模型的机会。

在小数据集的情况下,有一部分数据将被保留下来用于测试模型,这些数据可能具有重要的特征,而我们的模型可能会因为没有在这些数据上进行训练而错过。

(2) K-折交叉验证(K-fold)

(K-fold Cross Validation,记为K-CV或K-fold)

K-Fold交叉验证技术中,整个数据集被划分为K个大小相同的部分。每个分区被称为 一个”Fold”。所以我们有K个部分,我们称之为K-Fold。一个Fold被用作验证集,其余的K-1个Fold被用作训练集。

该技术重复K次,直到每个Fold都被用作验证集,其余的作为训练集。

模型的最终准确度是通过取k个模型验证数据的平均准确度来计算的。

(3) 分层k-折交叉验证Stratified k-fold

Stratified k-fold cross validation,

K-折交叉验证的变种, 分层的意思是说在每一折中都保持着原始数据中各个类别的比例关系,比如说:原始数据有3类,比例为1:2:1,采用3折分层交叉验证,那么划分的3折中,每一折中的数据类别保持着1:2:1的比例,这样的验证结果更加可信。

(4) 其它验证

去除p交叉验证)
留一交叉验证)
蒙特卡罗交叉验证
时间序列交叉验证

(5)API

from sklearn.model_selection import StratifiedKFold

说明:普通K折交叉验证和分层K折交叉验证的使用是一样的 只是引入的类不同

from sklearn.model_selection import KFold

使用时只是KFold这个类名不一样其他代码完全一样

strat_k_fold=sklearn.model_selection.StratifiedKFold(n_splits=5, shuffle=True, random_state=42)

n_splits划分为几个折叠 ​ shuffle是否在拆分之前被打乱(随机化),False则按照顺序拆分 ​ random_state随机因子

indexs=strat_k_fold.split(X,y)

返回一个可迭代对象,一共有5个折叠,每个折叠对应的是训练集和测试集的下标

然后可以用for循环取出每一个折叠对应的X和y下标来访问到对应的测试数据集和训练数据集 以及测试目标集和训练目标集

for train_index, test_index in indexs:

X[train_index] y[train_index] X[test_index ] y[test_index ]

(6)示例

from sklearn.datasets import load_iris
from sklearn.model_selection import StratifiedKFold
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
​
# 加载数据
iris = load_iris()
X = iris.data
y = iris.target
​
# 初始化分层k-折交叉验证器
#n_splits划分为几个折叠 
#shuffle是否在拆分之前被打乱(随机化),False则按照顺序拆分
#random_state随机因子
strat_k_fold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
​
# 创建一个K近邻分类器实例
knn = KNeighborsClassifier(n_neighbors=7)
​
# 进行交叉验证
accuracies = []
for train_index, test_index in strat_k_fold.split(X, y):print(train_index, test_index)X_train, X_test = X[train_index], X[test_index]y_train, y_test = y[train_index], y[test_index]
​# 数据预处理(标准化)scaler = StandardScaler()X_train_scaled = scaler.fit_transform(X_train)X_test_scaled = scaler.transform(X_test)
​# 使用K近邻分类器进行训练knn.fit(X_train_scaled, y_train)# 输出每次折叠的准确性得分score = knn.score(X_test,y_test)print(score)accuracies.append(score)#把分数添加到外面列表中
print(sum(accuracies)/len(accuracies))#平均得分
​
#使用StratifiedKFold来创建5个折叠,每个折叠中鸢尾花数据集的类别分布与整体数据集的分布一致。然后我们对每个折叠进行了训练和测试,计算了分类器的准确性。

2 超参数搜索

超参数搜索也叫网格搜索(Grid Search)

比如在KNN算法中,k是一个可以人为设置的参数,所以就是一个超参数。网格搜索能自动的帮助我们找到最好的超参数值。

3 sklearn API

class sklearn.model_selection.GridSearchCV(estimator, param_grid)

说明:
同时进行交叉验证(CV)、和网格搜索(GridSearch),GridSearchCV实际上也是一个估计器(estimator),同时它有几个重要属性:
     best_params_  最佳参数
     best_score_ 在训练集中的准确率
     best_estimator_ 最佳估计器
     cv_results_ 交叉验证过程描述
     best_index_最佳k在列表中的下标
参数:
    estimator: scikit-learn估计器实例
    param_grid:以参数名称(str)作为键,将参数设置列表尝试作为值的字典
        示例: {"n_neighbors": [1, 3, 5, 7, 9, 11]}
   cv: 确定交叉验证切分策略,值为:
       (1)None  默认5折
       (2)integer  设置多少折
       如果估计器是分类器,使用"分层k-折交叉验证(StratifiedKFold)"。在所有其他情况下,使用KFold。

4 示例-鸢尾花分类

用KNN算法对鸢尾花进行分类,添加网格搜索和交叉验证

# 用KNN算法对鸢尾花进行分类,添加网格搜索和交叉验证
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
​
def knn_iris_gscv():# 1)获取数据iris = load_iris()# 2)划分数据集x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)# 3)特征工程:标准化transfer = StandardScaler()x_train = transfer.fit_transform(x_train)x_test = transfer.transform(x_test)# 4)KNN算法预估器, 这里就不传参数n_neighbors了,交给GridSearchCV来传递estimator = KNeighborsClassifier()# 加入网格搜索与交叉验证, GridSearchCV会让k分别等于1,2,5,7,9,11进行网格搜索偿试。cv=10表示进行10次交叉验证estimator = GridSearchCV(estimator, param_grid={"n_neighbors": [1, 3, 5, 7, 9, 11]}, 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)  #0.9736842105263158
​# 最佳参数:best_params_print("最佳参数:\n", estimator.best_params_) #{'n_neighbors': 3}, 说明k=3时最好# 最佳结果:best_score_print("在训练集中的准确率:\n", estimator.best_score_)  #0.9553030303030303# 最佳估计器:best_estimator_print("最佳估计器:\n", estimator.best_estimator_) # KNeighborsClassifier(n_neighbors=3)# 交叉验证结果:cv_results_print("交叉验证过程描述:\n", estimator.cv_results_)#最佳参数组合的索引:最佳k在列表中的下标print("最佳参数组合的索引:\n",estimator.best_index_)#通常情况下,直接使用best_params_更为方便return None
​
knn_iris_gscv()

八 朴素贝叶斯分类

1 贝叶斯分类理论

假设现在我们有一个数据集,它由两类数据组成,数据分布如下图所示:

我们现在用p1(x,y)表示数据点(x,y)属于类别1(图中红色圆点表示的类别)的概率,用p2(x,y)表示数据点(x,y)属于类别2(图中蓝色三角形表示的类别)的概率,那么对于一个新数据点(x,y),可以用下面的规则来判断它的类别:

  • 如果p1(x,y)>p2(x,y),那么类别为1

  • 如果p1(x,y)<p2(x,y),那么类别为2

也就是说,我们会选择高概率对应的类别。这就是贝叶斯决策理论的核心思想,即选择具有最高概率的决策。已经了解了贝叶斯决策理论的核心思想,那么接下来,就是学习如何计算p1和p2概率。

2 条件概率

在学习计算p1 和p2概率之前,我们需要了解什么是条件概率(Conditional probability),就是指在事件B发生的情况下,事件A发生的概率,用P(A|B)来表示。

根据文氏图,可以很清楚地看到在事件B发生的情况下,事件A发生的概率就是P(A∩B)除以P(B)。

𝑃(𝐴|𝐵)=𝑃(𝐴∩𝐵)/𝑃(𝐵)

因此,

𝑃(𝐴∩𝐵)=𝑃(𝐴|𝐵)𝑃(𝐵)

同理可得,

𝑃(𝐴∩𝐵)=𝑃(𝐵|𝐴)𝑃(𝐴)

𝑃(𝐴|𝐵)=𝑃(B|A)𝑃(𝐴)/𝑃(𝐵)

这就是条件概率的计算公式。

3 全概率公式

除了条件概率以外,在计算p1和p2的时候,还要用到全概率公式,因此,这里继续推导全概率公式。

假定样本空间S,是两个事件A与A'的和。

上图中,红色部分是事件A,绿色部分是事件A',它们共同构成了样本空间S。

在这种情况下,事件B可以划分成两个部分。

即:

𝑃(𝐵)=𝑃(𝐵∩𝐴)+𝑃(𝐵∩𝐴′)

在上面的推导当中,我们已知

𝑃(𝐵∩𝐴)=𝑃(𝐵|𝐴)𝑃(𝐴)

所以:

𝑃(𝐵)=𝑃(𝐵|𝐴)𝑃(𝐴)+𝑃(𝐵|𝐴′)𝑃(𝐴′)

这就是全概率公式。它的含义是,如果A和A'构成样本空间的一个划分,那么事件B的概率,就等于A和A'的概率分别乘以B对这两个事件的条件概率之和。

将这个公式代入上一节的条件概率公式,就得到了条件概率的另一种写法:

P(A|B)=\frac{P(B|A)P(A)}{P(B|A)P(A)+P(B|A^,)P(A^,)}

4 贝叶斯推断

对条件概率公式进行变形,可以得到如下形式:

我们把P(A)称为"先验概率"(Prior probability),即在B事件发生之前,我们对A事件概率的一个判断。

P(A|B)称为"后验概率"(Posterior probability),即在B事件发生之后,我们对A事件概率的重新评估。

P(B|A)/P(B)称为"可能性函数"(Likelyhood),这是一个调整因子,使得预估概率更接近真实概率。

所以,条件概率可以理解成下面的式子:

后验概率 = 先验概率x调整因子

这就是贝叶斯推断的含义。我们先预估一个"先验概率",然后加入实验结果,看这个实验到底是增强还是削弱了"先验概率",由此得到更接近事实的"后验概率"。

5 朴素贝叶斯推断

理解了贝叶斯推断,那么让我们继续看看朴素贝叶斯。贝叶斯和朴素贝叶斯的概念是不同的,区别就在于“朴素”二字,朴素贝叶斯对条件概率分布做了条件独立性的假设。 比如下面的公式,假设有n个特征:

根据贝叶斯定理,后验概率 P(a|X) 可以表示为:

P(a|X) = \frac{P(X|a)P(a)}{P(X)}

其中:

  • P(X|a) 是给定类别 ( a ) 下观测到特征向量 $X=(x_1, x_2, ..., x_n) $的概率;

  • P(a) 是类别 a 的先验概率;

  • P(X) 是观测到特征向量 X 的边缘概率,通常作为归一化常数处理。

朴素贝叶斯分类器的关键假设是特征之间的条件独立性,即给定类别 a ,特征 $x_i$ 和 $x_j$ (其中 $$i \neq j$$ 相互独立。)

因此,我们可以将联合概率 P(X|a) 分解为各个特征的概率乘积:

P(X|a) = P(x_1, x_2, ..., x_n|a) = P(x_1|a)P(x_2|a)...P(x_n|a)

将这个条件独立性假设应用于贝叶斯公式,我们得到:

P(a|X) = \frac{P(x_1|a)P(x_2|a)...P(x_n|a)P(a)}{P(X)}

这样,朴素贝叶斯分类器就可以通过计算每种可能类别的条件概率和先验概率,然后选择具有最高概率的类别作为预测结果。

这样我们就可以进行计算了。如果有些迷糊,让我们从一个例子开始讲起,你会看到贝叶斯分类器很好懂,一点都不难。

纹理色泽鼔声类别
1清晰清绿清脆好瓜
2模糊乌黑浊响坏瓜
3模糊清绿浊响坏瓜
4清晰乌黑沉闷好瓜
5清晰清绿浊响好瓜
6模糊乌黑沉闷坏瓜
7清晰乌黑清脆好瓜
8模糊清绿沉闷好瓜
9清晰乌黑浊响坏瓜
10模糊清绿清脆好瓜
11清晰清绿沉闷
12模糊乌黑浊响?

示例:
p(a|X) = p(X|a)*p(a)/p(X)  #贝叶斯公式
p(X|a) = p(x1,x2,x3...xn|a) = p(x1|a)*p(x2|a)*p(x3|a)...p(xn|a)
p(X) = p(x1,x2,x3...xn) = p(x1)*p(x2)*p(x3)...p(xn)
p(a|X) = p(x1|a)*p(x2|a)*p(x3|a)...p(xn|a) * p(a) / p(x1)*p(x2)*p(x3)...p(xn)  #朴素贝叶斯公式

P(好瓜)=(好瓜数量)/所有瓜
P(坏瓜)=(坏瓜数量)/所有瓜
p(纹理清晰)=(纹理清晰数量)/所有瓜
p(纹理清晰|好瓜)= 好瓜中纹理清晰数量/好瓜数量
p(纹理清晰|坏瓜)= 坏瓜中纹理清晰数量/坏瓜数量

p(好瓜|纹理清晰,色泽清绿,鼓声沉闷)
    =【p(好瓜)】*【p(纹理清晰,色泽清绿,鼓声沉闷|好瓜)】/【p(纹理清晰,色泽清绿,鼓声沉闷)】
    =【p(好瓜)】*【p(纹理清晰|好瓜)*p(色泽清绿|好瓜)*p(鼓声沉闷|好瓜)】/【p(纹理清晰)*p(色泽清绿)*p(鼓声沉闷)】

p(坏瓜|纹理清晰,色泽清绿,鼓声沉闷)
    =【p(坏瓜)*p(纹理清晰|坏瓜)*p(色泽清绿|坏瓜)*p(鼓声沉闷|坏瓜)】/【p(纹理清晰)*p(色泽清绿)*p(鼓声沉闷)】

从公式中判断"p(好瓜|纹理清晰,色泽清绿,鼓声沉闷)"和"p(坏瓜|纹理清晰,色泽清绿,鼓声沉闷)"时,因为它们的分母
值是相同的,[值都是p(纹理清晰)*p(色泽清绿)*p(鼓声沉闷)],所以只要计算它们的分子就可以判断是"好瓜"还是"坏瓜"之间谁大谁小了,所以没有必要计算分母
p(好瓜) = 6/10
p(坏瓜)=4/10
p(纹理清晰|好瓜) = 4/6
p(色泽清绿|好瓜) = 4/6
p(鼓声沉闷|好瓜) = 2/6
p(纹理清晰|坏瓜) = 1/4
p(色泽清绿|坏瓜) = 1/4
p(鼓声沉闷|坏瓜) = 1/4
把以上计算代入公式的分子
p(好瓜)*p(纹理清晰|好瓜)*p(色泽清绿|好瓜)*p(鼓声沉闷|好瓜) = 4/45
p(坏瓜)*p(纹理清晰|坏瓜)*p(色泽清绿|坏瓜)*p(鼓声沉闷|坏瓜) = 1/160
所以
p(好瓜|纹理清晰,色泽清绿,鼓声沉闷) >  p(坏瓜|纹理清晰,色泽清绿,鼓声沉闷),
所以把(纹理清晰,色泽清绿,鼓声沉闷)的样本归类为好瓜

6 拉普拉斯平滑系数

某些事件或特征可能从未出现过,这会导致它们的概率被估计为零。然而,在实际应用中,即使某个事件或特征没有出现在训练集中,也不能完全排除它在未来样本中出现的可能性。拉普拉斯平滑技术可以避免这种“零概率陷阱”

公式为:

一般α取值1,m的值为总特征数量

通过这种方法,即使某个特征在训练集中从未出现过,它的概率也不会被估计为零,而是会被赋予一个很小但非零的值,从而避免了模型在面对新数据时可能出现的过拟合或预测错误

比如计算判断新瓜(纹理清晰,色泽淡白,鼓声沉闷)是好和坏时,因为在样本中色泽淡白没有出现,导致出现0值,会影响计算结果,要采用拉普拉斯平滑系数

p(好瓜|纹理清晰,色泽淡白,鼓声沉闷)
    =【p(好瓜)】*【p(纹理清晰|好瓜)*p(色泽淡白|好瓜)*p(鼓声沉闷|好瓜)】/【p(纹理清晰)*p(色泽淡白)*p(鼓声沉闷)】
p(坏瓜|纹理清晰,色泽淡白,鼓声沉闷)
    =【p(坏瓜)】*【p(纹理清晰|坏瓜)*p(色泽淡白|坏瓜)*p(鼓声沉闷|坏瓜)】/【p(纹理清晰)*p(色泽淡白)*p(鼓声沉闷)】  
p(纹理清晰|好瓜)= (4+1)/(6+3)  # +1是因为防止零概率 +3是因为有3个特征(纹理,色泽,鼓声)
p(色泽淡白|好瓜)= (0+1)/(6+3)  
p(鼓声沉闷|好瓜) = (2+1)/(6+3)
p(纹理清晰|坏瓜)= (1+1)/(4+3)  
p(色泽淡白|坏瓜)= (0+1)/(4+3)  
p(鼓声沉闷|坏瓜) = (1+1)/(4+3)  

7 sklearn API

sklearn.naive_bayes.MultinomialNB()
estimator.fit(x_train, y_train)
y_predict = estimator.predict(x_test)

8 sklearn 示例

示例:用朴素贝叶斯算法对鸢尾花的分类

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
# 1)获取数据
news =load_iris()
# 2)划分数据集
x_train, x_test, y_train, y_test = train_test_split(news.data, news.target)
# 3)特征工程:不用做标准化
# 4)朴素贝叶斯算法预估器流程
estimator = MultinomialNB()
estimator.fit(x_train, y_train)
# 5)模型评估
score = estimator.score(x_test, y_test)
print("准确率为:\n", score)
# 6)预测
index=estimator.predict([[2,2,3,1]])
print("预测:\n",index,news.target_names,news.target_names[index])

九 决策树-分类

1 概念

1、决策节点 通过条件判断而进行分支选择的节点。如:将某个样本中的属性值(特征值)与决策节点上的值进行比较,从而判断它的流向。

2、叶子节点 没有子节点的节点,表示最终的决策结果。

3、决策树的深度 所有节点的最大层次数。

决策树具有一定的层次结构,根节点的层次数定为0,从下面开始每一层子节点层次数增加

4、决策树优点:

可视化 - 可解释能力-对算力要求低

5、 决策树缺点:

容易产生过拟合,所以不要把深度调整太大了。

 

是动物会飞有羽毛
1麻雀111
2蝙蝠110
3飞机010
4熊猫100

是否为动物

是动物会飞有羽毛
1麻雀111
2蝙蝠110
4熊猫100

是否会飞

是动物会飞有羽毛
1麻雀111
2蝙蝠110

是否有羽毛

是动物会飞有羽毛
1麻雀111

2 基于信息增益决策树的建立

信息增益决策树倾向于选择取值较多的属性,在有些情况下这类属性可能不会提供太多有价值的信息,算法只能对描述属性为离散型属性的数据集构造决策树。

根据以下信息构建一棵预测是否贷款的决策树。我们可以看到有4个影响因素:职业,年龄,收入和学历。

职业年龄收入学历是否贷款
1工人365500高中
2工人422800初中
3白领453300小学
4白领2510000本科
5白领328000硕士
6白领2813000博士

(1) 信息熵

信息熵描述的是不确定性。信息熵越大,不确定性越大。信息熵的值越小,则D的纯度越高。

假设样本集合D共有N类,第k类样本所占比例为P_k

,则D的信息熵为

(2) 信息增益

信息增益是一个统计量,用来描述一个属性区分数据样本的能力。信息增益越大,那么决策树就会越简洁。这里信息增益的程度用信息熵的变化程度来衡量, 信息增益公式:

(3) 信息增益决策树建立步骤

第一步,计算根节点的信息熵

上表根据是否贷款把样本分成2类样本,"是"占4/6=2/3, "否"占2/6=1/3,

所以

第二步,计算属性的信息增益

<1> "职业"属性的信息增益

在职业中,工人占1/3, 工人中,是否代款各占1/2, 所以有

在职业中,白领占2/3, 白领中,是贷款占3/4, 不贷款占1/4, 所以有

所以有

最后得到职业属性的信息增益为:

<2>" 年龄"属性的信息增益(以35岁为界)

<3> "收入"属性的信息增益(以10000为界,大于等于10000为一类)

<4> "学历"属性的信息增益(以高中为界, 大于等于高中的为一类)

注意:  以上年龄使用35为界,收入使用10000为界,学历使用高中为界,实计API使用中,会有一个参数"深度", 属性中具体以多少为界会被根据深度调整。

第三步, 划分属性

对比属性信息增益发现,"收入"和"学历"相等,并且是最高的,所以我们就可以选择"学历"或"收入"作为第一个

决策树的节点, 接下来我们继续重复1,2的做法继续寻找合适的属性节点

3 基于基尼指数决策树的建立(了解)

基尼指数(Gini Index)是决策树算法中用于评估数据集纯度的一种度量,基尼指数衡量的是数据集的不纯度,或者说分类的不确定性。在构建决策树时,基尼指数被用来决定如何对数据集进行最优划分,以减少不纯度。

基尼指数的计算

对于一个二分类问题,如果一个节点包含的样本属于正类的概率是 (p),则属于负类的概率是 (1-p)。那么,这个节点的基尼指数 (Gini(p)) 定义为:

Gini(p) = 1 - p^2 - (1-p)^2 = 2p(1-p)

对于多分类问题,如果一个节点包含的样本属于第 k 类的概率是 $p_k$,则节点的基尼指数定义为:

Gini(p) = 1 - \sum_{k=1}^{K} p_k^2

基尼指数的意义

  • 当一个节点的所有样本都属于同一类别时,基尼指数为 0,表示纯度最高。

  • 当一个节点的样本均匀分布在所有类别时,基尼指数最大,表示纯度最低。

决策树中的应用

在构建决策树时,我们希望每个内部节点的子节点能更纯,即基尼指数更小。因此,选择分割特征和分割点的目标是使子节点的平均基尼指数最小化。具体来说,对于一个特征,我们计算其所有可能的分割点对应的子节点的加权平均基尼指数,然后选择最小化这个值的分割点。这个过程会在所有特征中重复,直到找到最佳的分割特征和分割点。

例如,考虑一个数据集 (D),其中包含 (N) 个样本,特征 (A) 将数据集分割为 $|D_1|$和 $|D_2|$ ,则特征 (A) 的基尼指数为:

Gini_A = \frac{|D_1|}{|D|} Gini(D_1) + \frac{|D_2|}{|D|} Gini(D_2)

其中 $|D_1|$和 $|D_2|$ 分别是子集 $D_1$ 和 $D_2$ 中的样本数量。

通过这样的方式,决策树算法逐步构建一棵树,每一层的节点都尽可能地减少基尼指数,最终达到对数据集的有效分类。

案例:

首先工资有两个取值,分别是0和1。当工资=1时,有3个样本。

所以:

同时,在这三个样本中,工作都是好。

所以:

就有了加号左边的式子:

同理,当工资=0时,有5个样本,在这五个样本中,工作有3个是不好,2个是好。

就有了加号右边的式子:

同理,可得压力的基尼指数如下:

平台的基尼指数如下:

在计算时,工资和平台的计算方式有明显的不同。因为工资只有两个取值0和1,而平台有三个取值0,1,2。所以在计算时,需要将平台的每一个取值都单独进行计算。比如:当平台=0时,将数据集分为两部分,第一部分是平台=0,第二部分是平台!=0(分母是5的原因)。

根据基尼指数最小准则, 我们优先选择工资或者平台=0作为D的第一特征。

我们选择工资作为第一特征,那么当工资=1时,工作=好,无需继续划分。当工资=0时,需要继续划分。

当工资=0时,继续计算基尼指数:

当平台=0时,基尼指数=0,可以优先选择。

同时,当平台=0时,工作都是好,无需继续划分,当平台=1,2时,工作都是不好,也无需继续划分。直接把1,2放到树的一个结点就可以。

4 sklearn API

class sklearn.tree.DecisionTreeClassifier(....)
参数:
criterion "gini" "entropy” 默认为="gini"
    当criterion取值为"gini"时采用 基尼不纯度(Gini impurity)算法构造决策树,
    当criterion取值为"entropy”时采用信息增益( information gain)算法构造决策树.
max_depth   int, 默认为=None  树的最大深度

# 可视化决策树
function sklearn.tree.export_graphviz(estimator, out_file="iris_tree.dot", feature_names=iris.feature_names)
参数:
    estimator决策树预估器
    out_file生成的文档
   feature_names节点特征属性名
功能:
   把生成的文档打开,复制出内容粘贴到"http://webgraphviz.com/"中,点击"generate Graph"会生成一个树型的决策树图

5 示例

示例1:鸢尾花分类

用决策树对鸢尾花进行分类

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeClassifier, export_graphviz
​
# 1)获取数据集
iris = load_iris()
​
# 2)划分数据集
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)
​
#3)标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
​
# 4)决策树预估器
estimator = DecisionTreeClassifier(criterion="entropy")
​
estimator.fit(x_train, y_train)
​
# 5)模型评估,计算准确率
score = estimator.score(x_test, y_test)
print("准确率为:\n", score)
​
# 6)预测
index=estimator.predict([[2,2,3,1]])
print("预测:\n",index,iris.target_names,iris.target_names[index])
​
# 可视化决策树
export_graphviz(estimator, out_file="iris_tree.dot", feature_names=iris.feature_names)
准确率为:0.8947368421052632

把文件"iris_tree.dot"内容粘贴到"Webgraphviz"点击"generate Graph"决策树图

示例2:坦尼克号乘客生存

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier, export_graphviz
# 1、获取数据
titanic = pd.read_csv("src/titanic/titanic.csv")
titanic.head()
# 筛选特征值和目标值
x = titanic[["pclass", "age", "sex"]]
y = titanic["survived"]
​
#2、数据处理
# 1)缺失值处理, 因为其中age有缺失值。
x["age"].fillna(x["age"].mean(), inplace=True)
​
# 2) 转换成字典, 因为其中数据必须为数字才能进行决策树,所在先转成字典,后面又字典特征抽取,这样之后的数据就会是数字了, 鸢尾花的数据本来就全部是数字,所以不需要这一步。
"""
x.to_dict(orient="records") 这个方法通常用于 Pandas DataFrame 对象,用来将 DataFrame 转换为一个列表,其中列表的每一个元素是一个字典,对应于 DataFrame 中的一行记录。字典的键是 DataFrame 的列名,值则是该行中对应的列值。
假设你有一个如下所示的 DataFrame x:A  B  C
0  1  4  7
1  2  5  8
2  3  6  9
执行 x.to_dict(orient="records"),你会得到这样的输出:
[{'A': 1, 'B': 4, 'C': 7},{'A': 2, 'B': 5, 'C': 8},{'A': 3, 'B': 6, 'C': 9}
]
"""
x = x.to_dict(orient="records")
# 3)、数据集划分
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=22)
# 4)、字典特征抽取
transfer = DictVectorizer()
x_train = transfer.fit_transform(x_train) #稀疏矩阵
x_test = transfer.transform(x_test)
​
# 3)决策树预估器
estimator = DecisionTreeClassifier(criterion="entropy", max_depth=8)
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)
​
​
# 6)预测
x_test = transfer.transform([{'pclass': '1rd', 'age': 22.0, 'sex': 'female'}])
index=estimator.predict(x_test)
print("预测1:\n",index)#[1]  头等舱的就可以活下来
x_test = transfer.transform([{'pclass': '3rd', 'age': 22.0, 'sex': 'female'}])
index=estimator.predict(x_test)
print("预测2:\n",index)#[0]  3等舱的活不下来
​
# 可视化决策树
export_graphviz(estimator, out_file="titanic_tree.dot", feature_names=transfer.get_feature_names_out())
http://www.xdnf.cn/news/465607.html

相关文章:

  • C++核心编程--3 函数提高
  • AAC 协议
  • 计量——异方差的检验及其修正
  • day26 Python 自定义函数
  • 解密企业级大模型智能体Agentic AI 关键技术:MCP、A2A、Reasoning LLMs- Manus解密
  • PPT处理控件Aspose.Slides教程:在 Java 中将 PPTX 转换为 EMF
  • Python控制Keysight DAQ973A/DAQ970A实现温度监测
  • .NET 8 kestrel 配置PEM,实现内网https
  • JavaScript - 运算符之逗号操作符与逗号分隔符(逗号操作符概述、逗号操作符用法、逗号分隔符、逗号分隔符用法)
  • 【C++重载操作符与转换】容器与继承
  • Excel函数使用介绍-分组求和SUMIF
  • 达利欧:“交易的艺术”与“背后的力量”
  • OpenCv高阶(4.0)——案例:海报的透视变换
  • 【杂谈】-AI 重塑体育营销:从内容管理到创意释放的全面变革
  • C#发送文件到蓝牙设备
  • 使用 `perf` 和火焰图(Flame Graph)进行性能分析
  • 25.5.15
  • MySQL读写分离
  • 深入解析C++模板:从基础到高级应用
  • LeetCode 热题 100 437. 路径总和 III
  • 运维职业发展思维导图
  • 建筑兔零基础人工智能自学记录92|类脑智能与脑机接口-7
  • vue3搭建脚手架前的前置知识
  • 【Unity】给出两个旋转角度,判断是应该左转还是右转
  • QT设置MySQL驱动
  • 已解决(亲测有效!):安装部署Docker Deskpot之后启动出现Docker Engine Stopped!
  • 11 web 自动化之 DDT 数据驱动详解
  • 文件目录与检索综合练习题
  • 面试 Linux 运维相关问题
  • 基于SpringBoot的家政服务系统设计与实现(源码+文档+部署讲解)