神经元
神经元是神经网络的基本单元,接受多个神经元传递过来的输入信号,然后通过激活函数计算输出信号。
从图里可以看到每个输入信号都有一个权重w,这个权重是动态改变的。我们平时所说的训练神经网络主要是训练(修正)这个权重w。
同时每个神经元有一个参数theta,这个theta是阈值,生物意义上,如果输入信号的加权和比阈值高,意味着这个神经元被激活(处于兴奋状态)。信号向下一个神经元传递,但是在这里的感知机模型里面,theta不过是个公式里的参数罢了。
感知机(Perceptron)
感知机本质上就是两个神经元构成的简单神经网络。一层是输入层,全部是输入神经元,直接把信号传递给下一层神经元,第二层就是输出层。
感知机使用Sigmoid函数作为激活函数:
使用Python语言可以用一行代码表示出来,不过得借助math库。
lambda s:1.0/(1+math.exp(-s))
每次感知机有输出的时候,内部参数(w)都需要被训练和调整,其训练算法如下:
学习率介于0和1之间,我们可以手动设置。算法本身很简单。
接下来,我们思考一下代码的实现:
- 首先,我们可以定义一个节点类Node用来表示一个神经元节点,从这个Node类可以进一步派生出输入节点类和输出节点类。
- 我们可以认为每个节点Node都有一个输入节点列表。对于输入节点,它的输入节点列表就是空集[]。
- 节点Node的默认激活函数是sigmoid函数。
- 本来输入节点的职能就是把输入信号传递给输出层,不需要激活函数的,但是我们也可以把它视为一个M-P神经元,它的输入信号加权和为0(它本身就是输入层,不存在额外的输入,)将它的阈值theta视为他要传递给输出层的数值的相反数。将它的激活函数设置为f(x)=x。就可以等同于一个M-P神经元了。
代码实现
import math
def sigmoid(x):
return 1.0/(1+math.exp(-x))
class Record:
def __init__(self):
feature_vector = []
label = None
return
class Node:
def __init__(self):
self.input_list = []
self.activated = False
self.recent_output = None
self.threshold = 0.0
self.activation_func = lambda s: 1.0 / (1 + math.exp(-s))
return
def add_input(self, node):
self.input_list.append([node, 1.0])
return
def set_threshold(self, th):
self.threshold = th
return
def output(self):
sum_ = 0.0
for p in self.input_list:
prev_node = p[0]
sum_ += prev_node.output() * p[1]
self.recent_output = self.activation_func(sum_ - self.threshold)
return self.recent_output
class InputNode(Node):
def __init__(self):
Node.__init__(self)
self.activation_func = lambda s: s
return
def set_input_val(self, val):
Node.set_threshold(self, -val)
return
class OutputNode(Node):
def __init__(self):
Node.__init__(self)
self.threshold = 4.0
return
class NeuralNetwork:
def __init__(self):
self.eta = 0.5
self.data_set = []
def set_data_set(self, data_set_):
self.data_set = data_set_
return
class SingleLayerNeuralNetwork(NeuralNetwork):
def __init__(self):
NeuralNetwork.__init__(self)
self.perceptron = OutputNode()
self.input_node_list = []
self.perceptron.threshold = 4.0
return
def add_input_node(self):
inode = InputNode()
self.input_node_list.append(inode)
self.perceptron.add_input(inode)
return
def set_input(self, value_list):
assert len(value_list) == len(self.input_node_list)
for index in range(0, len(value_list), 1):
value = value_list[index]
node = self.input_node_list[index]
node.set_input_val(value)
return
def adjust(self, label):
for prev_node_pair in self.perceptron.input_list:
delta_weight = self.eta * (label - self.perceptron.recent_output) * prev_node_pair[0].recent_output
origin_weight = prev_node_pair[1]
prev_node_pair[1] = origin_weight + delta_weight
return
def run(self):
for data in self.data_set:
self.set_input(data.feature_vector)
record_ = self.perceptron.output()
print record_
self.adjust(data.label)
return
- 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
现在让这个感知机来解决或问题(x∨y),假设1表示真,0表示假,那么1和1进行或运算结果就是1,1和0进行或运算结果就是1,0和0进行或运算结果就是0。
输入数据如下(一条记录保存为一行,第一个和第二个数字是输入,第3个数字是标签。数据假设保存在E://data/ann/train_0.txt):
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
1 0 1
0 0 0
1 0 1
1 1 1
1 1 1
0 1 1
1 0 1
0 0 0
- 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
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
有了以上代码和数据后,用以下Python代码开始跑训练集:
file_handler = open('E://data/ann/train_0.txt')
data_set = []
line = file_handler.readline()
while line:
record = Record()
item_feature_vector = []
str_list = line.split()
item_feature_vector.append(float(str_list[0]))
item_feature_vector.append(float(str_list[1]))
record.feature_vector = item_feature_vector
record.label = float(str_list[2])
data_set.append(record)
line = file_handler.readline()
print len(data_set)
ann = SingleLayerNeuralNetwork()
ann.add_input_node()
ann.add_input_node()
ann.set_data_set(data_set)
ann.run()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
结果如下图所示:
一开始的输出可能有点不准确,但是随着数据的增多,输出变得越来越像训练数据的真实值,比较逼近与0.0或者逼近与1.0。
实际上感知机能解决的问题很少,为了解决复杂问题,需要引入多层神经网络和新的学习算法:BP误差逆传播算法。
本篇文章主要摘自:机器学习笔记-Python实现感知Perceptron)在此非常感谢!
参考资料: