模式识别实验报告一 | |||
专业 | 学号 | 姓名 | 承担任务 |
电子信息 | 202222 | 任务123、报告 | |
电子信息 | 202222 | 任务4、报告 | |
背景:
基于提供的数据进行作业的分析。并假定男生、女生的身高、体重、鞋码、50m成绩、肺活量都服从正态分布。
作业内容:
- 以肺活量为例,画出男女生肺活量的直方图并做对比;
- 采用最大似然估计方法,求男女生肺活量的分布参数;
- 采用贝叶斯估计方法,求男女生肺活量的分布参数(方差已知,注明自己选定的参数情况);
- 基于身高和体重,采用最小错误率贝叶斯决策,画出类别判定的决策面。并判断某样本的身高体重分别为(165,50)时应该属于男生还是女生?为(175,55)时呢?
1.以肺活量为例,画出男女生肺活量的直方图并做对比;
1.1理论分析
首先适用python中的pandas库读取excel文件中的原始数据,且在读取数据时需要对异常数据进行数据清洗,保证数据的正确性,主要代码如下所示。经统计,原始数据中男女比例为8:2,如图1所示
利用python中的plt库进行直方图绘制,可得到男女生肺活量的直方图如图2、3所示。
图1
图2 男生肺活量直方图
图3女生肺活量直方图
1. students_data = pd.read_excel('data.xls') #读取excel文件
2. students_data.to_csv("data.csv",encoding="gbk")
3. #print(students_data.head())
4.
5. #异常数据处理
6. for i in range(len(students_data['性别 男1女0'])):
7. if( (students_data.loc[:,'性别 男1女0'].values[i] != 0.0) and (students_data.loc[:,'性别 男1女0'].values[i] != 1.0)):
8. sexProcess_data = students_data.drop(labels=i)
9.
10. #sexProcess_data['性别 男1女0'].value_counts().plot.pie(autopct = '%1.2f%%',)
11. #plt.title("数据中的男女比例的分布")
12. #plt.savefig("男女比例.png",dpi=400)
13. error_row = []
14. for i in range(len(sexProcess_data['肺活量'])):
15. if not isinstance(sexProcess_data['肺活量'].values[i], int):
16. error_row.append(i)
17.
18. vcProcess_data = sexProcess_data.drop(labels=error_row,axis = 0)
19.
20. vc_boy = []
21. vc_girl = []
22. weight_boy = []
23. weight_girl = []
24. height_boy = []
25. height_girl = []
26. for i in range(len(vcProcess_data)):
27. if ((vcProcess_data.loc[:,'性别 男1女0'].values[i]) == 1):
28. vc_boy.append(vcProcess_data.loc[:,'肺活量'].values[i])
29. weight_boy.append(vcProcess_data.loc[:,'体重(kg)'].values[i])
30. height_boy.append(vcProcess_data.loc[:,'身高(cm)'].values[i])
31. elif ((vcProcess_data.loc[:,'性别 男1女0'].values[i]) == 0):
32. vc_girl.append(vcProcess_data.loc[:,'肺活量'].values[i])
33. weight_girl.append(vcProcess_data.loc[:, '体重(kg)'].values[i])
34. height_girl.append(vcProcess_data.loc[:, '身高(cm)'].values[i])
2.采用最大似然估计方法,求男女生肺活量的分布参数;
2.1理论分析:
由题可知假设男女生的肺活量服从正态分布,即需采用最大似然估计的方法估计单变量的均值和方差两个参数。
假设变量服从正态分布,即式(1)所示:
px|μ=12πσexp-12x-μσ2#1
则似然函数如式(2)所示:
k=1Npxk|μ=12πσ2N2exp-xk-μ22σ2#2
取对数并对参数求导,令导数为0求得参数的最大似然估计为式(3)
μ=1Nk=1Nxkσ2=1Nk=1Nxk-μ2#3
2.2工程实现:
将最大似然估计封装为函数MLEmean(data),估计结果如图(1)所示。
图2.1最大似然估计参数
主要代码如下所示:
1. def MLEmean(data): #极大似然估计 只需输入数据
2. MLE = []
3. average = sum(data)/len(data)
4. MLE.append(average)
5. total_error = 0
6. for msg in data:
7. total_error += pow((msg - average),2)
8. variance = total_error / len(data)
9. MLE.append(variance)
10. return MLE
3.采用贝叶斯估计方法,求男女生肺活量的分布参数(方差已知,注明自己选定的参数情况);
3.1理论分析:
由题可知假设男女生的肺活量服从正态分布,即需要采用贝叶斯估计的方法估计服从正态分布单变量的均值和方差两个参数。
首先贝叶斯估计中假定参数μ服从正态分布如式(4)所示:
pμ=12πσexp-12μ-μ0σ2#4
导出μ的后验概率分布如式(5)所示:
pμ|x=pxμpμpxμpμdμ#5
分母中的积分项为常数,则化简式(5)可得式(6):
pμ|x=12πσNexp-12μ-μNσN2#6
根据后验概率可导出均值μ的贝叶斯估计如式(7)所示:
μ=Nσ02Nσ02+σ2μN+σ2Nσ02+σ2μ0#7
3.2工程实现:
本次实验中先验根据最大似然估计所得,取男生肺活量先验均值为4500、先验方差取10000,数据分布方差为550000;女生肺活量先验均值为3500、先验方差取10000,数据分布方差为550000。贝叶斯估计的结果如图(2)所示。
图2 贝叶斯估计参数结果
1. print("贝叶斯估计:")
2. def Bayesmean(data,priormean,priorvar,variance): #贝叶斯估计 输入为数据、先验均值、先验均值方差、先验数据方差
3. return int(priorvar*sum(data)+variance*priormean)/(len(data)*priorvar+variance)
4. Bayes_boy = Bayesmean(vc_boy,4500,10000,550000)
5. Bayes_girl = Bayesmean(vc_girl,3500,10000,550000)
6. print("男生肺活量均值为:",Bayes_boy)
7. print("女生肺活量均值为:",Bayes_girl)
4.基于身高和体重,采用最小错误率贝叶斯决策,画出类别判定的决策面。并判断某样本的身高体重分别为(165,50)时应该属于男生还是女生?为(175,55)时呢?
4.1理论分析:
正态分布下的最小错误率贝叶斯判别函数和决策面,利用样本集估计p(x|wi)和p(wi),得到估计值,利用代替贝叶斯决策中的p(x|wi)和p(wi),完成分类器设计决策面的求解问题实际上是要求我们去设计一个分类器,对于最小错误率贝叶斯决策来说,具体流程如下:
- 求出决策规则函数如式(8)所示:
gix=pxwipwi#8
其中,x代表的是随机变量,可以是一个特征向量,表示一个样本拥有多个特征;gix代表判别x属于第i类的决策规则函数;wi代表的是随机变量第个i类;p(x|wi)是一个联合高斯分布,如式(9)所示:
px∣wi=1(2π)d2Σi12exp-12x-μiTΣi-1x-μi#9
其中∑i为特征向量x的协方差矩阵。
- 简化求解过程,由于样本符合正态分布,对判别函数取对数,不会改变判变规则函数的单调性:
gix=lnpx∣wipwi
=-12x-μiT∑i-1x-μi-d2ln2π-ln12Σi+lnpwi#10
3. 导出决策方程如式(11)所示:
-12x-μiTΣi-1x-μi-x-μjTΣj-1x-μj-ln12ΣiΣj+lnpwipwj=0#11
4.2工程实现
从推导表达式来看,
gix-gjx
=-12x-μiTΣi-1x-μi-x-μjTΣj-1x-μj-ln12ΣiΣj+lnpwipwj=0
求得这样一个表达式,我们需要得到样本中男生女生的“体重”和“身高”这两个特征的均值μi、μj,男生女生的类概率pwi、pwj以及他们的“体重”“身高”的协方差矩阵i、Σj,因为这里的每个样本的特征向量都是二维的,所以协方差矩阵应该是2*2的矩阵。
协方差矩阵i、Σj求解结果如图3所示、代码块如下:
1. def covcal(x1,x2):
2. x1_mean = np.mean(x1)
3. x2_mean = np.mean(x2)
4. cov = 0
5. for i in range(len(x1)):
6. cov += (x1[i]-x1_mean)*(x2[i]-x2_mean)
7. cov = cov/(len(x1)-1)
8. return cov
9.
10. boy_cov11 = covcal(height_boy,height_boy)
11. boy_cov12 = boy_cov21 = covcal(height_boy,weight_boy)
12. boy_cov22 = covcal(weight_boy,weight_boy)
13. girl_cov11 = covcal(height_girl,height_girl)
14. girl_cov12 = girl_cov21 = covcal(height_girl,weight_girl)
15. girl_cov22 = covcal(weight_girl,weight_girl)
16. boy_covmatrix = np.array([boy_cov11,boy_cov12,boy_cov21,boy_cov22]).reshape(2,2)
17. girl_covmatrix = np.array([girl_cov11,girl_cov12,girl_cov21,girl_cov22]).reshape(2,2)
18.
19. print("男生样本数据协方差矩阵:")
20. print(boy_covmatrix)
21. print("女生样本数据协方差矩阵:")
22. print(girl_covmatrix)
图3 样本数据协方差矩阵
求解男生女生的类概率pwi、pwj以及他们的“体重”“身高”的协方差矩阵Σi、Σj代码块
1. def decisonfun(graph_high,graph_width):
2. graph_point = np.zeros(shape=(100,100))
3. for i in range(100):
4. for j in range(100):
5. sample_vector = np.matrix([[graph_high[i,j]],[graph_width[i,j]]])
6. graph_point[i,j]=0.5*np.transpose(sample_vector-boy_feature_mean)*(np.linalg.inv(boy_covmatrix))*\
7. (sample_vector-boy_feature_mean)-0.5*np.transpose(sample_vector-girl_feature_mean)*\
8. (np.linalg.inv(girl_covmatrix))*(sample_vector-girl_feature_mean)+\
9. 0.5*math.log((np.linalg.det(boy_covmatrix))/(np.linalg.det(girl_covmatrix)))-\
10. math.log(boy_priori_probability/girl_priori_probability)
11. return graph_point
12.
13. boy_feature_mean = np.matrix([[np.mean(boy_height)],[np.mean(boy_weight)]])
14. girl_feature_mean = np.matrix([[np.mean(girl_height)],[np.mean(girl_weight)]])
15. boy_priori_probability = len(boy_weight)/len(data)
16. girl_priori_probability = len(girl_weight)/len(data)
特征身高体重均值μi、μj求解如图4所示:
图4 样本数据均值
男生女生的类概率pwi、pwj如图5所示:
图5 样本类概率
根据上文求所得数据绘制下面表1。
表1计算决策面所需信息
男生 | 女生 | |
特征均值 | [174.36256545][67.29712042] | [163.05154639][50.88659794] |
概率 | 0.784394250513347 | 0.19917864476386038 |
特征向量协方差矩阵 |
决策面求解结果可视化代码块如下:
1. graph_high = np.linspace(140,200,100)
2. graph_width = np.linspace(30,120,100)
3. grid_graph_high,grid_graph_width = np.meshgrid(graph_high,graph_width)
4. plt.contourf(grid_graph_high,grid_graph_width,decisonfun(grid_graph_high,grid_graph_width),100,alpha=0)
5. grid_graph = plt.contour(grid_graph_high,grid_graph_width,decisonfun(grid_graph_high,grid_graph_width),0)
6. plt.clabel(grid_graph,inline=True,fontsize=4)
7. plt.ylim(30,120)
8. plt.xlim(140,200)
9. # 绘制男女生分布
10. boy_point = plt.scatter(boy_height, boy_weight, marker='.', linewidths=0.5, edgecolors = "g")
11. girl_point = plt.scatter(girl_height, girl_weight, marker='.', linewidths=0.5, edgecolors = "y")
12. plt.xlabel("身高(cm)")
13. plt.ylabel("体重(kg)")
14. plt.scatter(165,50,marker='*',linewidth=1)
15. plt.annotate((165,50),xy=(165,50))
16. plt.scatter(175,55,marker='*',linewidth=1)
17. plt.annotate((175,55),xy=(175,55))
18. plt.savefig("0.png",dpi=400)
图6男女生判别决策可视化
上图中蓝绿色曲线就是我们的决策方程,黄色点为女生样本身高体重二维数据,蓝色点为男生身高体重二维数据。绿色星星为身高165cm,体重50kg的分布点,红色星星为身高175cm,体重55kg的分布点。
由于样本特征为二维数据,所以求得的决策面为曲线由图可以看出我们计算出来的决策面基本可以正确划分男女类别,数据曲线下方的数据点就是样本数据中女生的“身高”“体重”样本点,曲线上方的数据点就是男生的“身高”“体重”样本点,符合理论推导。
由图可知,某样本的身高体重分别为(165,50)时应该属于女生,身高体重为(175,55)时应该属于男生。