机器学习作业2
来源:互联网 发布:抗抑郁药 知乎 编辑:程序博客网 时间:2024/06/03 14:31
MDS和ISOMAP降维
本作业使用MDS和ISOMAP两种降维算法,对耶鲁大学人脸数据集进行降维,然后使用作业1中的对率回归(逻辑回归)分类器进行训练。耶鲁大学人脸数据集下载自新浪微盘。
数据的读取
作业的分类目的是区分照片中的人是否有胡子,而原数据集中,有胡子的照片只有44张,远少于没有胡子的,所以我删去了55张没有胡子的人的照片。最终保留有胡子的照片44张,没有胡子的照片66张,共110张。代码中使用 PIL 的 Image 模块读取图片,并同时读取 Label 文件,Label 文件用 0 表示没有胡子,用 1 表示有胡子。
if __name__ == '__main__': print('正在读取数据并降维') data = np.empty([110, 10000], np.float32) for idx in range(110): image = Image.open('Data/s' + str(idx + 1) + '.bmp') data[idx] = np.reshape(image, [10000]) file = open('Data/labels.txt') label = np.array(file.readline().strip('\n').split(','), np.int32)
MDS降维函数
算法部分我就不说了,直接上图。内容来自周志华《机器学习》教材。
其中,
# 获取欧氏距离# data: 要获取欧氏距离的矩阵,大小 m * n# return:m * m 的矩阵,第 [i, j] 个元素代表 data 中元素 i 到元素 j 的欧氏距离def get_distance(data): data_count = len(data) mat_distance = np.zeros([data_count, data_count], np.float32) for idx in range(data_count): for sub_idx in range(data_count): mat_distance[idx][sub_idx] = np.linalg.norm(data[idx] - data[sub_idx]) return mat_distance
随后,按照算法要求完成MDS算法的编程。
# mds 算法的具体实现# data:需要降维的矩阵# target:目标维度# return:降维后的矩阵def mds(data, target): data_count = len(data) if target > data_count: target = data_count val_dist_i_j = 0.0 vec_dist_i_2 = np.zeros([data_count], np.float32) vec_dist_j_2 = np.zeros([data_count], np.float32) mat_b = np.zeros([data_count, data_count], np.float32) mat_distance = get_distance(data) for idx in range(data_count): for sub_idx in range(data_count): dist_ij_2 = np.square(mat_distance[idx][sub_idx]) val_dist_i_j += dist_ij_2 vec_dist_i_2[idx] += dist_ij_2 vec_dist_j_2[sub_idx] += dist_ij_2 / data_count vec_dist_i_2[idx] /= data_count val_dist_i_j /= np.square(data_count) for idx in range(data_count): for sub_idx in range(data_count): dist_ij_2 = np.square(mat_distance[idx][sub_idx]) mat_b[idx][sub_idx] = -0.5 * (dist_ij_2 - vec_dist_i_2[idx] - vec_dist_j_2[sub_idx] + val_dist_i_j) a, v = np.linalg.eig(mat_b) list_idx = np.argpartition(a, target - 1)[-target:] a = np.diag(np.maximum(a[list_idx], 0.0)) return np.matmul(v[:, list_idx], np.sqrt(a))
ISOMAP降维函数
ISO降维是另一种降维算法,但它也要用到MDS。书上对ISOMAP算法的描述如下:
因此,首先需要实现最短路径算法。在这里我选择的是 Dijkstra 算法。
# 使用 Dijkstra 算法获取最短路径,并更新距离矩阵# data: 距离矩阵,大小 m * m# src:最短路径的起始点,范围 0 到 m-1def dijkstra(data, src): inf = float('inf') data_count = len(data) col_u = data[src].copy() dot_remain = data_count - 1 while dot_remain > 0: dot_k = np.argpartition(col_u, 1)[1] length = data[src][dot_k] for idx in range(data_count): if data[src][idx] > length + data[dot_k][idx]: data[src][idx] = length + data[dot_k][idx] data[idx][src] = data[src][idx] dot_remain -= 1 col_u[dot_k] = inf
在ISOMAP算法中,首先获得每个数据点的
# isomap 算法的具体实现# data:需要降维的矩阵# target:目标维度# k:k 近邻算法中的超参数# return:降维后的矩阵def isomap(data, target, k): inf = float('inf') data_count = len(data) if k >= data_count: raise ValueError('K的值最大为数据个数 - 1') mat_distance = get_distance(data) knn_map = np.ones([data_count, data_count], np.float32) * inf for idx in range(data_count): top_k = np.argpartition(mat_distance[idx], k)[:k + 1] knn_map[idx][top_k] = mat_distance[idx][top_k] for idx in range(data_count): dijkstra(knn_map, idx) return mds(data, target)
搞定~接下来在 Main 中调用即可。在这里偷了个懒,由于Yale数据集中,每个人都有11张照片,所以我用10张训练,1张测试,总共有100张训练数据,10张测试数据,迭代500次。这里直接使用了 机器学习作业1 中提到的对率回归分类器。
# 对数据进行降维,从原先的 10000 维降低至 20 维,并保存到文件 # 然后使用作业一中的对率回归分类器进行训练,迭代次数 500 次 # 最后使用测试数据检验模型准确率,测试数据共 10 份 data_reduced = Reduction.isomap(data, 20, 15) np.savetxt('data_reduced.txt', data_reduced, '%.7e', '\t') sys.stdout.write('降维操作完成,低维度数据已保存到 data_reduced.txt\n') classifier = Classifier.Classifier(20) for repeat in range(500): for idx in range(110): if idx % 11 != 0: classifier.fit(data_reduced[idx], label[idx]) sys.stdout.write('\r正在训练,已完成 %.1f%%' % (repeat * 100 / 500)) sys.stdout.write('\r训练完毕,下面开始测试\n') correct_times = 0 for idx in range(10): val = classifier.classify(data_reduced[idx * 11]) print('第 %2d 次预测值:%d,真实值:%d' % (idx + 1, val, label[idx * 11])) if val == label[idx * 11]: correct_times += 1 print('测试完毕,准确率:%.2f%%' % (correct_times * 100 / 10))
运行结果
在 Python 3.5 的环境中,运行结果如下:
正在读取数据并降维
降维操作完成,低维度数据已保存到 data_reduced.txt
训练完毕,下面开始测试
第 1 次预测值:0,真实值:0
第 2 次预测值:1,真实值:1
第 3 次预测值:0,真实值:0
第 4 次预测值:0,真实值:0
第 5 次预测值:0,真实值:0
第 6 次预测值:0,真实值:0
第 7 次预测值:1,真实值:1
第 8 次预测值:0,真实值:0
第 9 次预测值:1,真实值:1
第 10 次预测值:1,真实值:1
测试完毕,准确率:100.00%
同时,程序将降维后的数据保存到了 txt 文件中,取其中一份数据放上来:
2.7251480e+02 4.0315417e+02 -5.1114426e+02 -6.7107399e+01 2.8956531e+02 -3.9103143e+00 -9.1109747e+02 7.2691174e+02 3.5637573e+02 9.6454456e+02 -3.3063428e+02 -5.5546588e+02 -9.0832664e+01 3.0922861e+02 -7.5431165e+02 -1.1431976e+02 7.9602502e+02 5.0018698e+02 3.3077114e+03 -2.6078193e+03
详细代码和数据文件请访问:
https://coding.net/u/dapanbest/p/MLHomeworks/git/tree/master/DimensionReduction
完结撒花!
- 机器学习作业2
- 机器学习第2周编程作业
- coursera 机器学习作业
- 机器学习作业1
- 机器学习作业笔记
- 机器学习作业3
- 机器学习作业4
- 机器学习作业5
- 机器学习作业6
- 机器学习作业7
- 机器学习作业8
- 【机器学习】作业8
- 机器学习作业9
- 机器学习技法第一次作业
- 机器学习技法作业7
- 机器学习技法第二次作业
- 机器学习基石第二次作业
- 机器学习技法第三次作业
- LeetCode——128. Longest Consecutive Sequence
- centos 安装 jdk
- 第三章 汇编语言和汇编软件
- Python报错'module' object is not callable
- 17. Letter Combinations of a Phone Number
- 机器学习作业2
- Intellij IDEA 安装lombok及使用详解
- java中的String.join
- Vue $emit $refs子父组件间方法的调用
- HDU 6116 路径计数(组合数学+NTT)
- Android学习笔记16---星级评分条的实现
- 开启博客之旅
- 1098: 树状数组2(破坏公路)
- 第十三课 创建高级联结