Python入门到实战(十三)过拟合欠拟合、混淆矩阵、评价指标、模型建立与优化、炮弹轨迹预测、芯片品质预测
模型过拟合与欠拟合
— | 训练数据 | 预测数据 |
---|---|---|
欠拟合 | 不准确 | 不准确 |
合适模型 | 准确 | 准确 |
过拟合 | 准确 | 不准确 |
欠拟合
产生原因:训练集不充分、模型过于简单不够适应场景需求
解决办法:增加模型复杂度 增加样本维数 增加数据样本
过拟合
产生原因:模型过于复杂、数据中噪音过多、训练数据分配不足
解决办法:适当简化模型、按照一定规则扩充样本数据、数据预处理、保留主成分信息、增加正则项
机器学习过程中,模型求解的核心目标就是最小化损失函数,增加正则项是指
在损失函数中添加一个额外项,实现对求解参数的数值约束,防止模型过拟合。
混淆矩阵Confusion Matrix
混淆矩阵也称误差矩阵,用于统计各类别样本预测正确与错误的数量,能帮助用户更全面地评估模型表现。
— | positive | negative |
---|---|---|
True | TP(真正例) | FN(假反例) |
False | FP(假正例) | TN(真反例) |
TP预测准确,实际为正样本
TN预测准确,实际为负样本
FP预测错误,预测为正样本、实际为负样本
FN预测错误,预测为负样本、实际为正样本
基于混淆矩阵的评价指标:
准确率accuracy
预测正确的比例:
accuracy=(TP+TN)/(TP+TN+FP+FN)
错误率misclassification rate
预测错误的比例:
misclassification rate=(FN+FP)/(TP+TN+FP+FN)
查准率Precision
预测结果为正的样本中预测正确的比例
Precision=(TP)/(TP+FP)
查全率Recall
正样本中,预测正确的比例
Recall=(TP)/(TP+FN)
特异度Specificity
负样本中,预测正确的比例
Specificity=TN/(TN+FP)
F1分数
综合了precision和recall的指标
F1=(2PrecisionRecall)/(Precision+Recall)
应用优势:
如广告投放问题,需要关注查全率,即更多的用户被查找出来、同时需要关注查准率,即当中都是目标用户
异常消费检测中希望判断正常的消费(负样本)中尽可能不存在异常的消费,需要关注特异度
模型建立与优化
算法选择:
— | 核心结构、参数设置 | — |
---|---|---|
逻辑回归 | –> | 边界函数线性;二阶高阶多项式 |
KNN | –> | 核心参数k取多少合适 |
决策树 | –> | 树分支逻辑、最小分支样本数 |
朴素贝叶斯 | –> | 高斯、伯努利、CategoricalNB |
神经网络 | –> | 几层、每层神经元数、激活函数 |
其他算法 | –> |
实战
炮弹轨迹预测
数据载入和可视化
import pandas as pd
import numpy as np
data_train=pd.read_csv('Final_task1_train_data.csv')
data_test=pd.read_csv('Final_task1_test_data.csv')
#数据赋值
x_train=data_train.loc[:,'x_d']
y_train=data_train.loc[:,'y_d']
x_test=data_test.loc[:,'x_d']
y_test=data_test.loc[:,'y_d']
#数据可视化
from matplotlib import pyplot as plt
fig1=plt.figure()
data_train=plt.scatter(x_train,y_train,label='training data')
data_test=plt.scatter(x_test,y_test,label='test data')
plt.title('traing-test data')
plt.xlabel('x_d')
plt.ylabel('y_d')
plt.show()
数据预处理、训练模型和预测
#数据预处理]
x_train=np.array(x_train)
x_train=x_train.reshape(-1,1)
x_test=np.array(x_test).reshape(-1,1)
#线性回归模型建立与训练
from sklearn.linear_model import LinearRegression
model1=LinearRegression()
model1.fit(x_train,y_train)
#模型预测
y_train_predict=model1.predict(x_train)
y_test_predict=model1.predict(x_test)
print(y_test_predict)
[193.2015545 207.52252667 224.53579682 245.97018916 280.65629028
358.35826068 383.81445438 392.54847322]
模型评估与可视化、r2分数
#模型评估
from sklearn.metrics import r2_score
r2_train=r2_score(y_train,y_train_predict)
r2_test=r2_score(y_test,y_test_predict)
print('training r2:',r2_train)
print('test r2:',r2_test)
#可视化模型预测结果 生成新的数据点
x_range=np.linspace(40,400,300).reshape(-1,1)
y_range_predict=model1.predict(x_range)
#结果可视化
fig2=plt.figure()
data_train=plt.scatter(x_train,y_train,label='training data')
data_test=plt.scatter(x_test,y_test,label='test data')
curve_p=plt.plot(x_range,y_range_predict,'r',label='predicted curve')
plt.title('traing-test data')
plt.xlabel('x_d')
plt.ylabel('y_d')
plt.show()
training r2: 0.5756251457400434
test r2: -1.6553718247964802
二次多项式属性数据
#生成二阶属性数据
from sklearn.preprocessing import PolynomialFeatures
poly2=PolynomialFeatures(degree=2)
x_2_train=poly2.fit_transform(x_train)
x_2_test=poly2.fit_transform(x_test)
#建立新的回归模型
model2=LinearRegression()
model2.fit(x_2_train,y_train)
#模型预测评估
y_2_train_predict=model2.predict(x_2_train)
y_2_test_predict=model2.predict(x_2_test)
r2_2_train=r2_score(y_train,y_2_train_predict)
r2_2_test=r2_score(y_test,y_2_test_predict)
print(r2_2_train,r2_2_test)
#结果可视化
x_range=np.linspace(40,400,300).reshape(-1,1)
x_2_range=poly2.transform(x_range)
y_2_range_predict=model2.predict(x_2_range)
fig3=plt.figure()
data_train=plt.scatter(x_train,y_train,label='training data')
data_test=plt.scatter(x_test,y_test,label='test data')
curve_p=plt.plot(x_range,y_2_range_predict,'r',label='predicted cruve')
plt.title('traing-test data(poly2)')
plt.xlabel('x_d')
plt.ylabel('y_d')
plt.legend()
plt.show()
0.9954725354913146 0.9738532191575348
六次多项式属性数据
0.9996745021380762 -3.5695788694551593
总结
回归对应着欠拟合的模型
二阶模型对应着正确的模型
六阶对应着过拟合的模型
芯片品质预测
数据加载可视化
#加载数据
import pandas as pd
import numpy as np
data=pd.read_csv('Final_task2_data.csv')
#赋值
x=data.drop(['y'],axis=1)
y=data.loc[:,'y']
#数据可视化
from matplotlib import pyplot as plt
fig1=plt.figure()
bad=plt.scatter(x.loc[:,'x1'][y==0],x.loc[:,'x2'][y==0],marker='x',s=150,label='bad')
good=plt.scatter(x.loc[:,'x1'][y==1],x.loc[:,'x2'][y==1],marker='o',facecolor='none',edgecolor='red',s=150,label='good')
plt.title('chip data')
plt.xlabel('size 1')
plt.ylabel('size 2')
plt.legend()
plt.show()
import math
x1=data.loc[:,'x1'][y==0]
x2=data.loc[:,'x2'][y==0]
#计算均值与标准差
u1=x1.mean()
sigma1=x1.std()
u2=x2.mean()
sigma2=x2.std()
print(u1,sigma1,u2,sigma2)
#计算高斯分布的概率密度函数
p1 = 1/sigma1/math.sqrt(2*math.pi)*np.exp(-np.power((x1-u1),2)/2/math.pow(sigma1,2))
p2 = 1/sigma2/math.sqrt(2*math.pi)*np.exp(-np.power((x2-u2),2)/2/math.pow(sigma2,2))
p=np.multiply(p1,p2)
x1=data.loc[:,'x1'][y==1]
x2=data.loc[:,'x2'][y==1]
#计算均值与标准差
u1=x1.mean()
sigma1=x1.std()
u2=x2.mean()
sigma2=x2.std()
print(u1,sigma1,u2,sigma2)
#计算高斯分布的概率密度函数
p1 = 1/sigma1/math.sqrt(2*math.pi)*np.exp(-np.power((x1-u1),2)/2/math.pow(sigma1,2))
p2 = 1/sigma2/math.sqrt(2*math.pi)*np.exp(-np.power((x2-u2),2)/2/math.pow(sigma2,2))
p=np.multiply(p1,p2)
寻找异常点并剔除
#异常数据点对点检测
from sklearn.covariance import EllipticEnvelope
ad_model = EllipticEnvelope(contamination=0.02)
ad_model.fit(x[y==0])
y_predict_bad = ad_model.predict(x[y==0])
print(y_predict_bad)
[ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 -1]
fig2=plt.figure()
bad=plt.scatter(x.loc[:,'x1'][y==0],x.loc[:,'x2'][y==0],marker='x',s=150,label='bad')
good=plt.scatter(x.loc[:,'x1'][y==1],x.loc[:,'x2'][y==1],marker='o',facecolor='none',edgecolor='red',s=150,label='good')
plt.scatter(x.loc[:,'x1'][y==0][y_predict_bad==-1],x.loc[:,'x2'][y==0][y_predict_bad==-1],marker='o',s=150)
plt.title('chip data')
plt.xlabel('size 1')
plt.ylabel('size 2')
plt.legend()
plt.show()
#剔除异常数据点
data = data.drop(index=35)
统计各维度数据分布
#各维度数据分布
fig3 = plt.figure()
plt.subplot(121)
plt.hist(x1,bins=10)
plt.title('x1 data')
plt.xlabel('x1')
plt.ylabel('counts')
plt.subplot(122)
plt.hist(x2,bins=10)
plt.title('x2 data')
plt.xlabel('x2')
plt.ylabel('counts')
plt.show()
对数据进行主成分分析,计算各维度方差比例
#X y赋值
X = data.drop(['y'],axis=1)
y = data.loc[:,'y']
#主成分分析
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
X_norm = StandardScaler().fit_transform(X)
pca = PCA(n_components=2)
X_reduced = pca.fit_transform(X_norm)
var_ratio = pca.explained_variance_ratio_
print(var_ratio)
fig4 = plt.figure()
plt.bar([1,2],var_ratio)
plt.xticks([1,2],['PC1','PC2'])
plt.show()
数据分离 分离参数0.4
#数据分离
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=1,test_size=0.4)
建立KNN模型k=3完成分类
#建立knn模型 k=3
from sklearn.neighbors import KNeighborsClassifier
knn_3 = KNeighborsClassifier(n_neighbors=3)
knn_3.fit(X_train,y_train)
#模型预测
y_train_predict = knn_3.predict(X_train)
y_test_predict = knn_3.predict(X_test)
from sklearn.metrics import accuracy_score
accuracy_train = accuracy_score(y_train,y_train_predict)
accuracy_test = accuracy_score(y_test,y_test_predict)
print(accuracy_train,accuracy_test)
0.8095238095238095 0.7857142857142857
可视化分类边界
#结果可视化
#生成用于结果可视化的数据集
xx,yy = np.meshgrid(np.arange(0,10,0.05),np.arange(0,10,0.05))
#数据展开
x_range = np.c_[xx.ravel(),yy.ravel()]
#预测生成的数据对应的类别
y_range_predict = knn_3.predict(x_range)
fig4 = plt.figure()
bad_p = plt.scatter(x_range[:,0][y_range_predict==0],x_range[:,1][y_range_predict==0],label='bad_p')
good_p = plt.scatter(x_range[:,0][y_range_predict==1],x_range[:,1][y_range_predict==1],label='good_p')
bad = plt.scatter(X.loc[:,'x1'][y==0],X.loc[:,'x2'][y==0],marker='x',s=150,label='bad')
good = plt.scatter(X.loc[:,'x1'][y==1],X.loc[:,'x2'][y==1],marker='o',facecolor='none',edgecolor='red',s=150,label='good')
plt.title('chip data')
plt.xlabel('size 1')
plt.ylabel('size 2')
plt.legend()
plt.show()
评价指标
#计算混淆矩阵
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test,y_test_predict)
print(cm)
[[4 1]
[2 7]]
#获取混淆矩阵元素
TP = cm[1,1]
TN = cm[0,0]
FP = cm[0,1]
FN = cm[1,0]
accuracy = (TP+TN)/(TP+TN+FP+FN)
print(accuracy)
0.7857142857142857
recall = TP/(TP + FN)
print(recall)
0.7777777777777778
specificity = TN/(TN + FP)
print(specificity)
0.8
precision = TP/(TP + FP)
print(precision)
0.875
f1 = 2*precision*recall/(precision+recall)
print(f1)
0.823529411764706
尝试不同K值1-20并计算准确率
#尝试不同的k值并计算准确率
n = [i for i in range(1,21)]
accuracy_train = []
accuracy_test = []
for i in n:
knn_i = KNeighborsClassifier(n_neighbors=i)
knn_i.fit(X_train,y_train)
y_train_predict = knn_i.predict(X_train)
y_test_predict = knn_i.predict(X_test)
accuracy_train_i = accuracy_score(y_train,y_train_predict)
accuracy_test_i = accuracy_score(y_test,y_test_predict)
accuracy_train.append(accuracy_train_i)
accuracy_test.append(accuracy_test_i)
print(accuracy_train,accuracy_test)
#k值变化对准确率影响的结果可视化
fig10 = plt.figure(figsize=(12,5))
plt.subplot(121)
plt.plot(n,accuracy_train,marker='o')
plt.title('training data accuracy ')
plt.xlabel('k')
plt.ylabel('accuracy')
plt.subplot(122)
plt.plot(n,accuracy_test,marker='o')
plt.title('test data accuracy ')
plt.xlabel('k')
plt.ylabel('accuracy')
plt.show()