2023.10.4学习
人工智能基础学习
决策树(Decision Tree)
一种对实例进行分类的树形结构,通过多层判断区分目标所属类别。
本质:通过多层判断,从训练数据集中归纳出一组分类规则。
优点:计算量小,运算速度快;易于理解,可清晰查看各属性的重要性。
缺点:忽略属性间的相关性;样本类别分布不均匀时,容易影响模型表现。
决策树求解:
假设给定训练数据集
D
=
{
(
x
1
,
y
1
)
,
(
x
2
,
y
2
)
,
.
.
.
,
(
x
N
,
y
N
)
}
D = \lbrace (x_1,y_1),(x_2,y_2),...,(x_N,y_N)\rbrace
D={(x1,y1),(x2,y2),...,(xN,yN)}
其中,xi为输入实例,yi为类标记,N为样本容量。
求解目标:根据训练数据集构建一个决策树模型,使它能够对实例进行正确的分类。
问题核心:特征选择。在每一个节点,应该选用哪个特征。
三种求解方法:ID3、C4.5、CART。
ID3:利用信息熵原理选择信息增益最大的属性作为分类属性,递归地拓展决策树的分支,完成决策树的构造。
信息熵(entropy)是度量随机变量不确定性的指标,熵越大,变量的不确定性就越大。假定当前样本集合D中第k类样本所占的比例为pk,则D的信息熵为:
E n t ( D ) = − ∑ k = 1 ∣ y ∣ p k l o g 2 p k Ent(D) = -\sum \limits^{|y|}\limits_{k=1}p_klog_2p_k Ent(D)=−k=1∑∣y∣pklog2pk
Ent(D)的值越小,变量的不确定性越小。
根据信息熵,可以计算以属性a进行样本划分带来的信息增益(划分前的信息熵-划分后的信息熵):
G a i n ( D , a ) = E n t ( D ) − ∑ v = 1 V D v D E n t ( D v ) Gain(D,a) = Ent(D)-\sum \limits^V \limits_{v=1}\frac {D_v} D Ent(D_v) Gain(D,a)=Ent(D)−v=1∑VDDvEnt(Dv)
V为根据属性a划分出来的类别数、D为当前总样本数,Dv为类别 v 的样本数。
目标:划分后样本分布不确定性尽可能小,即划分后信息熵小,信息增益大。
代码:
import pandas as pd
from matplotlib import pyplot as plt
from sklearn import tree
# 原文件为.data类型,将其转化为dataFrame
data = pd.read_csv('iris.data', header=None, sep=',')
print(data.head())
# 添加列名称
data = data.rename(columns={0: 'sepal_length', 1: 'sepal_width', 2: 'petal_length', 3: 'petal_width', 4: 'class'})
print(data.head())
X = data.drop('class', axis=1)
y = data.loc[:, 'class']
# 创建决策树实例
# 第一个参数:指用信息增益最大化的方法选择节点,即使用ID3算法;第二个参数:该决策树不超过5个节点,防止过拟合
dc_tree = tree.DecisionTreeClassifier(criterion='entropy', min_samples_leaf=5)
dc_tree.fit(X, y)
# 可视化决策树
# 参数:filled=True,指同一种类别填充同一种颜色
tree.plot_tree(dc_tree, filled=True, feature_names=['sepal_length', 'sepal_width', 'petal_length', 'petal_width'],
class_names=['setosa', 'versicolor', 'virginica'])
plt.show()
异常检测(Anomaly Detection)
根据输入数据,对不符合预期模式的数据进行识别。
from sklearn.covariance import EllipticEnvelope
- 一维数据集:寻找低概率数据/事件
步骤:
(1)计算数据均值μ、标准差σ
(2)计算对应的高斯分布概率函数
p
(
x
)
=
1
σ
2
π
e
−
(
x
−
μ
)
2
2
σ
2
p(x) = \frac 1 {\sigma \sqrt{2\pi}} e^{-\frac {(x-\mu)^2} {2\sigma^2}}
p(x)=σ2π1e−2σ2(x−μ)2
(3)根据数据点概率,进行判断:若p(x) < ε(一般为0.5),则该点为异常点
- 高维数据集
步骤:
(1)计算数据均值μ1、μ2、μ3…,标准差σ1、σ2、σ3…
(2)计算概率密度函数p(x)(连乘)
p
(
x
)
=
∏
j
=
1
n
p
(
x
j
;
μ
j
,
σ
j
2
)
=
∏
j
=
1
n
1
σ
j
2
π
e
−
(
x
j
−
μ
j
)
2
2
σ
j
2
p(x)=\prod^n_{j =1}p(x_j;\mu_j,\sigma_j^2)=\prod^n_{j=1}\frac 1 {\sigma_j\sqrt{2\pi}}e^{-\frac{(x_j-\mu_j)^2} {2\sigma_j^2}}
p(x)=j=1∏np(xj;μj,σj2)=j=1∏nσj2π1e−2σj2(xj−μj)2
(3)若p(x) < ε,则该点为异常点
代码:
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from scipy.stats import norm
from sklearn.covariance import EllipticEnvelope
data = pd.read_csv('data2.csv')
print(data.head())
x = data.loc[:, 'x']
y = data.loc[:, 'y']
fig1 = plt.figure()
plt.scatter(x, y)
plt.show()
# 数据分布统计与可视化
fig2 = plt.subplot(121)
plt.hist(x, bins=100) # bins = 100表示横轴共分为100个小格
fig3 = plt.subplot(122)
plt.hist(y, bins=100)
plt.show()
# 计算数据均值和标准差
x_mean = x.mean() # 均值
x_sigma = x.std() # 标准差
y_mean = y.mean()
y_sigma = y.std()
# 绘制高斯分布曲线(概率密度函数曲线)
x_range = np.linspace(0, 100, 1000) # 横轴范围,0: 20, 300间隔
normal1 = norm.pdf(x_range, x_mean, x_sigma) # 生成曲线
fig4 = plt.figure()
plt.plot(x_range, normal1)
plt.show()
y_range = np.linspace(0, 100, 1000)
normal2 = norm.pdf(y_range, y_mean, y_sigma)
fig5 = plt.figure()
plt.plot(y_range, normal2)
plt.show()
# 直接用sklearn中的工具包拟合
clf = EllipticEnvelope(contamination=0.02) # contamination: 概率阈值,默认为0.1,但有时可能过高,会把正常点也判断成了异常点
clf.fit(data)
# 异常点预测与标记(返回值:y_predict==-1,表明为异常点)
y_predict = clf.predict(data)
fig6 = plt.figure()
un_normal_points = plt.scatter(data.loc[:, 'x'][y_predict == -1], data.loc[:, 'y'][y_predict == -1],
marker='o', facecolor='none', edgecolors='red', s=100) # marker:绘制点的形状;facecolor:填充;edgecolors:边框颜色;s:大小
normal_points = plt.scatter(x, y, marker='x')
plt.show()
主成分分析(PCA)
数据降维:在某些限定条件下,降低随机变量个数,得到一组“不相关”主变量的过程。
作用:减少模型分析数据量,提升处理效率,降低计算难度;实现数据可视化。
PCA:实现数据降维的方法。
from sklearn.decomposition import PCA
目标:寻找k(k<n)维新数据,使它们反映事物的主要特征。
核心:在信息损失尽可能少的情况下,降低数据维度。
如何保留主要信息:投影后的不同特征数据尽可能分得开(不相关),即,使投影后数据的方差最大,方差越大数据越分散。
步骤:
(1)原始数据预处理(标准化:μ = 0,σ = 1)
(2)计算协方差矩阵特征向量、数据在各特征向量投影后的方差
(3)根据需求(任务指定或方差比例),确定降维维度k
(4)选取k维特征向量,计算数据在其形成空间的投影
代码:
import pandas as pd
from matplotlib import pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
data = pd.read_csv('iris.data', header=None, sep=',')
print(data.head())
data = data.rename(columns={0: 'sepal_length', 1: 'sepal_width', 2: 'petal_length', 3: 'petal_width', 4: 'class'})
print(data.head())
X = data.drop('class', axis=1)
y = data.loc[:, 'class']
# KNN分类
KNN = KNeighborsClassifier(n_neighbors=3)
KNN.fit(X, y)
y_predict = KNN.predict(X)
accuracy = accuracy_score(y, y_predict)
print(accuracy)
# PCA分类
# 数据标准化处理(取第一个维度)
X_norm = StandardScaler().fit_transform(X)
print(X_norm)
fig1 = plt.figure(figsize=(20,5))
plt.subplot(121)
plt.hist(X.loc[:, 'sepal_length'], bins=100)
plt.subplot(122)
plt.hist(X_norm[:, 0], bins=100)
plt.show()
# 计算均值
x1_mean = X.loc[:, 'sepal_length'].mean()
x1_norm_mean = X_norm[:, 0].mean()
x1_sigma = X.loc[:, 'sepal_length'].std()
x1_norm_sigma = X_norm[:, 0].std()
print(x1_mean, x1_sigma, x1_norm_mean, x1_norm_sigma)
# 创建PCA实例
print(X.shape)
pca = PCA(n_components=4) # 参数:维度为4
X_pca = pca.fit_transform(X_norm) # 降维后的数据
# 查看所有主成分方差,只保留方差较高的主成分
var_ratio = pca.explained_variance_ratio_
print(var_ratio)
# 结果可视化
fig2 = plt.figure()
plt.bar([1, 2, 3, 4], var_ratio)
plt.xticks([1, 2, 3, 4], ['PC1', 'PC2', 'PC3', 'PC4'])
plt.ylabel('variance ratio of each PC')
plt.show()
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_norm) # 降维后的数据
print(X_pca.shape) # (150, 2)
print(type(X_pca)) #numpy.ndarray
fig3 = plt.figure()
setosa = plt.scatter(X_pca[:, 0][y == 'Iris-setosa'], X_pca[:, 1][y == 'Iris-setosa'])
ver = plt.scatter(X_pca[:, 0][y == 'Iris-versicolor'], X_pca[:, 1][y == 'Iris-versicolor'])
vir = plt.scatter(X_pca[:, 0][y == 'Iris-virginica'], X_pca[:, 1][y == 'Iris-virginica'])
plt.legend((setosa, ver, vir), ('setosa', 'versicolor', 'virginica'))
plt.show()
# 将降维后的数据用于KNN分类,比较分类准确率
KNN = KNeighborsClassifier(n_neighbors=3)
KNN.fit(X_pca, y)
y_predict = KNN.predict(X_pca)
accuracy = accuracy_score(y, y_predict)
print(accuracy)