EM算法
在统计计算中,最大期望(EM)算法是在概率(probabilistic)模型中寻找参数最大似然估计或者最大后验估计的算法,其中概率模型依赖于无法观测的隐藏变量(Latent Variable)。最大期望经常用在机器学习和计算机视觉的数据聚类(Data Clustering)领域。
最大期望算法经过两个步骤交替进行计算:
第一步是计算期望(E),利用概率模型参数的现有估计值,计算隐藏变量的期望;
第二步是最大化(M),利用E 步上求得的隐藏变量的期望,对参数模型进行最大似然估计。
M 步上找到的参数估计值被用于下一个 E 步计算中,这个过程不断交替进行。
总体来说,EM的算法流程如下:
1.初始化分布参数
2.重复直到收敛:
E步骤:估计未知参数的期望值,给出当前的参数估计。
M步骤:重新估计分布参数,以使得数据的似然性最大,给出未知变量的期望估计。
朴素贝叶斯
朴素贝叶斯模型中,特征之间不仅仅是独立的,而且是加条件的独立的。比如说:我的特征向量x中,有n个特征 ,那么我可以把概率写成下面的形式: P(x|ωj)=P(x1|ωj)∗P(x2|ωj)∗P(x3|ωj)∗⋯∗P(xn|ωj)=∏k=1nP(xk|ωj)
代码实现
import numpy as np def em_algorithm(data, validnum, total, ep=1e-5): # validnum为数据中有效的样本数 #total为样本总数,ep为收敛精度 valid_data = data[0:validnum] avg = np.sum(valid_data) / total #avg为隐变量的均值,theta为隐变量的方差 theta = np.sum(np.square(valid_data)) / total - avg while True: s1 = np.sum(valid_data) + avg * (total - validnum) s2 = np.sum(np.square(valid_data)) + (avg * avg + theta) * (total - validnum) new_avg = s1 / total new_theta = s2 / total - new_avg * new_avg if new_avg - avg <= ep and new_theta - theta <= ep: break else: avg, theta = new_avg, new_theta return avg, theta def generation(dtype1, dtype2, dtype3,latent_idx): # build NAIVE bayesian avg, var = [], [] for idx in range(latent_idx): dim_type1, dim_type2, dim_type3 = dtype1[:, idx], dtype2[:, idx], dtype3[:,idx] # dim_type1 和 dim_type2 表示多维数据中的一维 avg.append([np.average(dim_type1), np.average(dim_type2), np.average(dim_type3)]) var.append([np.var(dim_type1), np.var(dim_type2), np.var(dim_type3)]) em_avg_type1, em_var_type1 = em_algorithm(dtype1[:40, #用EM算法估计缺失值均值和方差 latent_idx], 20, 40) em_avg_type2, em_var_type2 = em_algorithm(dtype2[:40, latent_idx], 20, 40) em_avg_type3, em_var_type3 = em_algorithm(dtype3[:40, latent_idx], 20, 40) avg.append([em_avg_type1, em_avg_type2, em_avg_type3]) # 估计得到均值和方差加入到数组 var.append([em_var_type1, em_var_type2, em_avg_type3]) return avg, var def calc_gaussian(x, avg, var): # 高斯分布函数 t = 1.0 / np.sqrt(2 * np.pi * var) return t * np.exp(-np.square(x - avg) / (2.0 * var)) if __name__ == '__main__': data_str = open('iris.data').readlines() data_type1 = np.ndarray([50, 4]) data_type2 = np.ndarray([50, 4]) data_type3 = np.ndarray([50, 4]) for idx in range(50): data_type1[idx] = data_str[idx].strip('\n').split(',')[0:4] for idx in range(50, 100): data_type2[idx - 50] = data_str[idx].strip('\n').split(',')[0:4] for idx in range(100, 150): data_type3[idx - 100] = data_str[idx].strip('\n').split(',')[0:4] a, v = generation(data_type1[:40], data_type2[:40], data_type3[:40], 3) # 构造测试数据集 data_test = np.concatenate((data_type1[40:], data_type2[40:], data_type3[40:])) correct_times = 0 for data_idx in range(len(data_test)): data = data_test[data_idx] val_type1, val_type2,val_type3 = 1/3,1/3, 1/3 for idx in range(4): # 朴素贝叶斯计算 val_type1 *= calc_gaussian(data[idx], a[idx][0], v[idx][0]) val_type2 *= calc_gaussian(data[idx], a[idx][1], v[idx][1]) val_type3 *= calc_gaussian(data[idx], a[idx][2], v[idx][2]) # 前10条数据为类型1,中间10条数据为类型2,后10条为类型3 if val_type1 > val_type2 and val_type1 > val_type3 and data_idx < 10: correct_times += 1 elif val_type1 < val_type2 and val_type2 > val_type3 and 20 > data_idx >= 10: correct_times += 1 elif val_type3 > val_type2 and val_type3 > val_type1 and data_idx >= 20: correct_times += 1 print("N0%2d, Iris_setosa: %f, Iris_versicolor: %f, Iris_virginica: %f" % (data_idx + 1, val_type1, val_type2,val_type3)) print("Accuracy: %.1f%%" % (correct_times * 100/30))
运行结果: