coding utf-8 import copy import pickle import random class NN object d

  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
# -*- coding: utf-8 -*-
import copy
import pickle
import random
class NN(object):
def __init__(self, in_count, out_count):
assert isinstance(in_count, int) and in_count > 0, "Param 'in_count' must be int and more 0"
assert isinstance(out_count, int) and out_count > 0, "Param 'out_count' must be int and more 0"
self._in_count = in_count
self._out_count = out_count
self._neurons = []
self._neurons = [[round(random.random() / 10, 3) for _ in xrange(self._in_count)] for _ in xrange(out_count)]
self._fn = None
@staticmethod
def load_from_file(fn):
nn = NN(1, 1)
nn._load_from_file(fn)
nn._fn = fn
return nn
def _load_from_file(self, fn):
f = open(fn, 'rb')
obj = copy.deepcopy(pickle.load(f))
f.close()
self._in_count = obj['in_count']
self._out_count = obj['out_count']
self._neurons = obj['neurons']
def save_to_file(self, fn=None):
if fn is None:
if self._fn:
fn = self._fn
else:
raise AttributeError("Filename is unset")
f = open(fn, 'wb')
obj = {'in_count': self._in_count,
'out_count': self._out_count,
'neurons': self._neurons}
pickle.dump(copy.deepcopy(obj), f)
f.close()
self._fn = fn
def calc(self, in_data, out_count=None, return_list=False):
if out_count is None:
out_count = self._out_count
else:
assert isinstance(out_count, int) and 0 < out_count <= self._out_count,\
"Param 'out_count' must be int and between 1 and %d" % self._out_count
assert isinstance(in_data, list) and len(in_data) == self._in_count,\
"Param 'in_data' must be list and len must be %d" % self._in_count
if return_list:
assert out_count == self._out_count, "For 'return_list' param 'out_count' must be %s" % self._out_count
w = self.get_all_weight(in_data)
if return_list:
return w
else:
if self._out_count == out_count:
return dict(zip(xrange(self._out_count), w))
else:
out = {}
s = sorted(xrange(self._out_count), key=lambda k: w[k])
s.reverse()
for i in xrange(out_count):
out[s[i]] = w[s[i]]
return out
def get_weight(self, in_data, neuron_index):
assert isinstance(in_data, list) and len(in_data) == self._in_count,\
"Param 'in_data' must be list and len must be %d" % self._in_count
assert isinstance(neuron_index, int) and 0 <= neuron_index < self._out_count,\
"Param 'neuron_index' must be int and between 1 and %d" % (self._out_count - 1)
sum = 0
for i in xrange(self._in_count):
if in_data[i]:
sum += in_data[i] * self._neurons[neuron_index][i]
return sum
def get_all_weight(self, in_data):
assert isinstance(in_data, list) and len(in_data) == self._in_count,\
"Param 'in_data' must be list and len must be %d" % self._in_count
weights = [0] * self._out_count
for i in xrange(self._in_count):
if in_data[i]:
for n in xrange(self._out_count):
weights[n] += in_data[i] * self._neurons[n][i]
return weights
def training(self, in_data, out_index, add_weight=0.001, add_true_weight=0.00005):
assert isinstance(in_data, list) and len(in_data) == self._in_count,\
"Param 'in_data' must be list and len must be %d" % self._in_count
assert isinstance(out_index, int) and 0 <= out_index < self._out_count,\
"Param 'out_index' must be int and between 1 and %d" % (self._out_count - 1)
ix = self.calc(in_data, 1).popitem()[0]
if ix != out_index:
result, add = False, add_weight
else:
result, add = True, add_true_weight
if add:
for i in xrange(self._in_count):
if in_data[i]:
self._neurons[out_index][i] += in_data[i] * add
return result
def training_all(self, data, iterations=100, percent_errors=10, print_progress=False):
data_len = len(data)
if print_progress:
print "Training (iterations: %d, percent_errors: %.2f%%, count data: %d)..." %\
(iterations, percent_errors, data_len)
n = 0
while n < iterations:
fails = 0
for i in xrange(data_len):
if not self.training(data[i][0], data[i][1]):
fails += 1
errors = (float(fails) / data_len) * 100
if print_progress:
print 'Errors: %.2f%%' % errors
if errors <= percent_errors:
n += 1
if print_progress:
print 'Training complete: %.2f%%' % ((float(n) / iterations) * 100)
if print_progress:
print "Training completed sucessfully."
def test(self, data):
n = 0
for i in xrange(len(data)):
ix = self.calc(data[i][0], 1).popitem()[0]
if data[i][1] == ix:
n += 1
return (float(n) / len(data)) * 100
if __name__ == '__main__':
DATA_VALUES = 'XYZ'
data = [([1, 0, 0, 0, 1,
0, 1, 0, 1, 0,
0, 0, 1, 0, 0,
0, 1, 0, 1, 0,
1, 0, 0, 0, 1], DATA_VALUES.index('X')),
([1, 0, 0, 0, 1,
0, 1, 0, 1, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0], DATA_VALUES.index('Y')),
([1, 1, 1, 1, 1,
0, 0, 0, 1, 0,
0, 0, 1, 0, 0,
0, 1, 0, 0, 0,
1, 1, 1, 1, 1], DATA_VALUES.index('Z'))]
test = [([1, 0, 0, 0, 1,
0, 1, 0, 1, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
1, 1, 0, 0, 1], DATA_VALUES.index('X')),
([1, 0, 0, 0, 1,
0, 1, 0, 1, 0,
0, 0, 1, 0, 0,
1, 0, 1, 0, 0,
0, 0, 0, 0, 0], DATA_VALUES.index('Y')),
([1, 1, 1, 1, 1,
0, 0, 0, 1, 0,
0, 0, 1, 0, 1,
0, 0, 0, 0, 0,
1, 1, 1, 1, 1], DATA_VALUES.index('Z'))]
nn = NN(5 * 5, len(DATA_VALUES))
nn.training_all(data, 10000, 0.1, True)
print 'Test result %.2f%%' % nn.test(test)