机器学习作业1 - 对率回归(逻辑回归)
2017-09-28 21:06
239 查看
使用10折交叉验证法和留一法评测对率回归分类器
标题有点长哈……这是第一次作业,来自周志华《机器学习》作业3.4,题目如下:选择两个UCI数据集,比较10折交叉验证法和留一法所估计出的对率回归(逻辑回归)的错误率。
那么,首先下载数据。实验中我使用的是 Iris 和 Wine 这两个数据集,前者简单点,后者复杂点。要注意的是,这两个数据集都是3个分类,为了偷个懒,我就把第三个分类删了,保留前两个分类。
分类器
对率回归分类器还是很简单的,大体思路如下:假设输入数据维度 m,我们保存一个权重向量,在计算的时候直接计算 m 和权重向量的点积,然后将点积结果加上偏置值,最后将计算结果通过 Sigmoid 函数,并输出预测结果。
为了方便起见,可以把偏置值一起放到权重向量中去,此时只要在数据中加上常数1即可,设加上常数以后的数据维度为 m + 1,则权重向量维度也为 m + 1。接下来给出损失函数如下。关于该函数的推导过程,斯坦福大学机器学习课程–逻辑回归算法 这篇博文已经写的非常详细了,大家可以直接看看。
L(θ)=−1m∑i=1m[yilogh0(xi)+(1−yi)log(1−h0(xi))]
那么,现在的目标是使得损失函数最小,因为损失函数越小代表着我们模型的预测结果越准确。接下来使用梯度下降法,基本思想是:在损失函数的结果中,对权重向量的每个元素求偏导,并按照比例(学习速率)对权重进行修改。这样一来,权重将向着减少损失函数值的方向发展。具体的推导过程同样可见上面那篇博文。分类器代码如下:
import numpy as np class Classifier(object): def __init__(self, attr_count, learn_rate=0.05): self.__attr_count__ = attr_count self.__learn_rate__ = learn_rate self.__weight__ = np.zeros(shape=[attr_count + 1], dtype=np.float32) def fit(self, value, label): value = np.append(value, [1.0]) linear_result = np.dot(value, self.__weight__) sigmoid_result = 1.0 / (np.exp(-linear_result) + 1.0) for idx in range(self.__attr_count__ + 1): update_val = (sigmoid_result - label) * value[idx] self.__weight__[idx] -= self.__learn_rate__ * update_val def classify(self, value): value = np.append(value, [1.0]) linear_result = np.dot(value, self.__weight__) if (1.0 / (np.exp(-linear_result) + 1.0)) > 0.5: return 1 else: return 0
准备数据
训练数据的准备很简单,直接使用 Python 的文件操作,读入数据文件即可。其中涉及到一些数组的切片操作,为了提高学习效率,在训练之前使用 numpy 打乱了数据集。if __name__ == '__main__': # 读入并打乱 Wine 数据集 data_str = open('Data/wine.data').readlines() np.random.shuffle(data_str) # 使用数组切片操作,分离数据和标签 wine_value = np.ndarray([len(data_str), 13], np.float32) wine_label = np.ndarray([len(data_str)], np.int32) for outer_idx in range(len(data_str)): data = data_str[outer_idx].strip('\n').split(',') wine_value[outer_idx] = data[1:] wine_label[outer_idx] = data[0] # 进行训练和测试 test_main(wine_value, wine_label, 13)
训练和验证
因为之前的分类器已经提供好了训练和测试的函数,所以直接调用即可。接下来使用10折交叉验证法和留一法进行验证。10折交叉验证法:将数据等分为10份,每次用其中9份训练,剩下1份测试,然后统计10次测试的评价错误率。
留一法:将数据分为 k 份(k为数据大小),每次用 k - 1 条数据训练,用1条测试,统计总体错误率。
使用简单的循环语句即可实现上述方法:
def test_main(value, label, attr_count): batch_size = len(value) // 10 total_correct_times = 0 for idx in range(10): print('10折交叉验证:当前第 %d 次' % (idx + 1)) correct_times = 0 classifier = LinearClassifier.Classifier(attr_count) value_train = np.append(value[0:idx * batch_size], value[(idx + 1) * batch_size:], axis=0) label_train = np.append(label[0:idx * batch_size], label[(idx + 1) * batch_size:], axis=0) value_test = value[idx * batch_size:(idx + 1) * batch_size] label_test = label[idx * batch_size:(idx + 1) * batch_size] for repeat in range(TRAIN_TIMES): for sub_idx in range(len(value_train)): classifier.fit(value_train[sub_idx], label_train[sub_idx]) for sub_idx in range(len(value_test)): result = classifier.classify(value_test[sub_idx]) if result == label_test[sub_idx]: correct_times += 1 total_correct_times += correct_times print('准确率:%.2f%%\n' % (correct_times * 100 / len(value_test))) print('10折交叉验证结束,平均准确率:%.2f%%\n' % (total_correct_times * 100 / len(value))) total_times = len(value) correct_times = 0 for idx in range(total_times): print('留一法第 %d 次,共 %d 次' % (idx, total_times)) classifier = LinearClassifier.Classifier(attr_count) value_train = np.append(value[0:idx], value[(idx + 1):], axis=0) label_train = np.append(label[0:idx], label[(idx + 1):], axis=0) value_test = value[idx] label_test = label[idx] for repeat in range(TRAIN_TIMES): for sub_idx in range(len(value_train)): classifier.fit(value_train[sub_idx], label_train[sub_idx]) result = classifier.classify(value_test) if result == label_test: correct_times += 1 print('留一法验证结束,准确率:%.2f%%' % (correct_times * 100 / total_times))
运行结果
代码在 Python 3.5 环境中执行结果如下:使用 wine.data 进行验证
10折交叉验证:当前第 1 次准确率:84.62%
10折交叉验证:当前第 2 次
准确率:84.62%
10折交叉验证:当前第 3 次
准确率:92.31%
10折交叉验证:当前第 4 次
准确率:92.31%
10折交叉验证:当前第 5 次
准确率:69.23%
10折交叉验证:当前第 6 次
准确率:84.62%
10折交叉验证:当前第 7 次
准确率:69.23%
10折交叉验证:当前第 8 次
准确率:92.31%
10折交叉验证:当前第 9 次
准确率:84.62%
10折交叉验证:当前第 10 次
准确率:92.31%
10折交叉验证结束,平均准确率:84.62%
开始使用留一法验证
留一法验证结束,准确率:83.85%
使用 iris.data 进行验证
10折交叉验证:当前第 1 次准确率:100.00%
10折交叉验证:当前第 2 次
准确率:100.00%
10折交叉验证:当前第 3 次
准确率:100.00%
10折交叉验证:当前第 4 次
准确率:100.00%
10折交叉验证:当前第 5 次
准确率:100.00%
10折交叉验证:当前第 6 次
准确率:100.00%
10折交叉验证:当前第 7 次
准确率:100.00%
10折交叉验证:当前第 8 次
准确率:100.00%
10折交叉验证:当前第 9 次
准确率:100.00%
10折交叉验证:当前第 10 次
准确率:100.00%
10折交叉验证结束,平均准确率:100.00%
开始使用留一法验证
留一法验证结束,准确率:100.00%
从结果可见,10折交叉验证法和留一法结果基本一致,而 Iris 数据集由于数据维度较低,预测效果明显好于 Wine 数据集。
详细代码和数据文件请访问:
https://coding.net/u/dapanbest/p/MLHomeworks/git/tree/master/LinearModel
完结撒花!
相关文章推荐
- 斯坦福机器学习Coursera课程:第三周作业--逻辑回归
- 机器学习二 逻辑回归作业
- 机器学习二 逻辑回归作业
- 机器学习二 逻辑回归作业
- stanford coursera 机器学习编程作业 exercise 3(逻辑回归实现多分类问题)
- Stanford机器学习---第三讲. 逻辑回归和过拟合问题的解决 logistic Regression & Regularization
- 机器学习系列(2)_从初等数学视角解读逻辑回归
- Coursera 机器学习(by Andrew Ng)课程学习笔记 Week 3——逻辑回归、过拟合与正则化
- 【机器学习】逻辑回归原理及其实现
- 机器学习之逻辑斯提回归(Logistic Regression)模型
- 机器学习(二)逻辑回归
- 机器学习之逻辑回归 Logistic Regression(一)
- 机器学习之逻辑回归(Logistic Regression)
- 机器学习:逻辑回归
- 听课笔记(第十讲): 逻辑斯蒂回归 (台大机器学习)
- 机器学习-对线性回归、逻辑回归、各种回归的概念学习
- 机器学习笔记-6.5逻辑回归的代价函数及其求导
- 机器学习之逻辑回归改善模型
- 机器学习之逻辑回归python实现
- 机器学习之逻辑回归(Logistic Regression)