Perception Machine In MNIST

感知机模型在MNIST数据集上的应用

感知机模型简介:

感知机模型是二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,取{+1,-1}二者。感知机对应于输入空间中将实例划分为正负两类的分离超平面,属于判别模型。感知机学习旨在求出将训练数据进行线性划分的分离超平面,为此,导入基于误分类的损失函数,利用梯度下降法对损失函数进行极小化,求得感知机模型。感知机学习算法具有简单而易实现的优点。
感知机模型选择的是误分类点到超平面的总距离为损失函数。直觉上我们选择误分类的总点数作为损失函数,但是这样的损失函数不是参数的可导函数。
感知机模型中一个实例点被误分类的时候,我们调整w和b的参数,使得分类超平面向误分类点的一侧移动以减少误分类点到分类超平面的距离。

实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : PerceptionMachine.py
# @Author: mfzhu
# @Date : 2017/4/21
# @Desc :
import numpy as np
import random
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import time
def binary(data, threshold):
"""
:param data: 需要二值化的数据
:param threshold: 二值化的阈值
:return: 二值化后的数据
"""
index_1 = np.array(data > threshold)
index_2 = np.array(data <= threshold)
data[index_1] = 1
data[index_2] = 0
return data
class PerceptionMachine(object):
def __init__(self):
self.max_iteration = 10000
# 迭代次数
self.step = 0.001
# 迭代步长
self.weight = []
# 权重向量
self.bias = 1
# 偏置
self.object_num = 1
# 此处认为标签为1的为+1类,为0的为-1类
def train(self, train_data, train_label):
"""
:param train_data: 训练数据
:param train_label: 训练标签
:return:
"""
num_sample, num_feature = train_data.shape
# 得到输入训练数据的样本数和每个样本的维度
self.weight = np.zeros(num_feature, float)
# 初始化权重向量为全0向量
time = 0
# 记录当前迭代次数
while time < self.max_iteration:
index = random.randint(0, num_sample - 1)
# 随机选取一个训练样本
sample = train_data[index, :]
label = train_label[index]
# 得到这个样本的标签和数据
y = int(label == self.object_num) * 2 - 1
# 判断是属于+1类还是-1类
result = (np.dot(sample, self.weight) + self.bias) * y
# 计算是否被误分类
if result <= 0:
self.weight += self.step * y * sample
self.bias += self.step * y
time += 1
# 被误分类的情况下,更新权重和偏置,然后迭代次数加1
def predict(self, features):
"""
:param features: 预测数据集合
:return: 返回集合中每个sample的预测标签
"""
res = []
for index in range(features.shape[0]):
if np.dot(features[index], self.weight) + self.bias > 0:
# 如果对应的线性函数大于0,则判断为1
res.append(1)
else:
res.append(0)
return res
if __name__ == '__main__':
print("Start reading the data:")
time1 = time.time()
raw_path = r'F:\work and learn\ML\dataset\MNIST\train.csv'
raw_data = np.loadtxt(raw_path, delimiter=',', skiprows=1)
# 读入原始数据
label = raw_data[:, 0]
data = raw_data[:, 1:]
# 区分标签数据和原始数据
data = binary(data, 125)
label[label != 0] = 1
# 进行二值化和对标签二值化(这边做的是二分类)
train_data, test_data, train_label, test_label = train_test_split(data, label, test_size=0.333, random_state=23333)
# 将数据随机切分用于训练和预测
time2 = time.time()
print("read data cost:", time2 - time1, " seconds", '\n')
print("Start training:")
perception = PerceptionMachine()
perception.train(train_data, train_label)
# 生成感知机模型并进行训练
time3 = time.time()
print("training cost:", time3 - time2, " seconds", '\n')
print("Start predicting:")
res = perception.predict(test_data)
score = accuracy_score(test_label, res)
time4 = time.time()
print("predict cost", time4 - time3, " seconds", '\n')
# 对数据进行预测并计算正确率
print("the accuracy_score is", score)

代码运行结果:

img