├── .vscode └── .ropeproject │ ├── config.py │ └── objectdb ├── BPNN.py ├── BPNN.pyc ├── DoubanRateLoader.py ├── DoubanRateLoader.pyc ├── GradientDescent.py ├── IrisDataSet.csv ├── IrisLoader.py ├── IrisLoader.pyc ├── douban_rate.csv ├── readme.md ├── test_classification.py └── test_regression.py /.vscode/.ropeproject/config.py: -------------------------------------------------------------------------------- 1 | # The default ``config.py`` 2 | # flake8: noqa 3 | 4 | 5 | def set_prefs(prefs): 6 | """This function is called before opening the project""" 7 | 8 | # Specify which files and folders to ignore in the project. 9 | # Changes to ignored resources are not added to the history and 10 | # VCSs. Also they are not returned in `Project.get_files()`. 11 | # Note that ``?`` and ``*`` match all characters but slashes. 12 | # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc' 13 | # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc' 14 | # '.svn': matches 'pkg/.svn' and all of its children 15 | # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o' 16 | # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o' 17 | prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject', 18 | '.hg', '.svn', '_svn', '.git', '.tox'] 19 | 20 | # Specifies which files should be considered python files. It is 21 | # useful when you have scripts inside your project. Only files 22 | # ending with ``.py`` are considered to be python files by 23 | # default. 24 | #prefs['python_files'] = ['*.py'] 25 | 26 | # Custom source folders: By default rope searches the project 27 | # for finding source folders (folders that should be searched 28 | # for finding modules). You can add paths to that list. Note 29 | # that rope guesses project source folders correctly most of the 30 | # time; use this if you have any problems. 31 | # The folders should be relative to project root and use '/' for 32 | # separating folders regardless of the platform rope is running on. 33 | # 'src/my_source_folder' for instance. 34 | #prefs.add('source_folders', 'src') 35 | 36 | # You can extend python path for looking up modules 37 | #prefs.add('python_path', '~/python/') 38 | 39 | # Should rope save object information or not. 40 | prefs['save_objectdb'] = True 41 | prefs['compress_objectdb'] = False 42 | 43 | # If `True`, rope analyzes each module when it is being saved. 44 | prefs['automatic_soa'] = True 45 | # The depth of calls to follow in static object analysis 46 | prefs['soa_followed_calls'] = 0 47 | 48 | # If `False` when running modules or unit tests "dynamic object 49 | # analysis" is turned off. This makes them much faster. 50 | prefs['perform_doa'] = True 51 | 52 | # Rope can check the validity of its object DB when running. 53 | prefs['validate_objectdb'] = True 54 | 55 | # How many undos to hold? 56 | prefs['max_history_items'] = 32 57 | 58 | # Shows whether to save history across sessions. 59 | prefs['save_history'] = True 60 | prefs['compress_history'] = False 61 | 62 | # Set the number spaces used for indenting. According to 63 | # :PEP:`8`, it is best to use 4 spaces. Since most of rope's 64 | # unit-tests use 4 spaces it is more reliable, too. 65 | prefs['indent_size'] = 4 66 | 67 | # Builtin and c-extension modules that are allowed to be imported 68 | # and inspected by rope. 69 | prefs['extension_modules'] = [] 70 | 71 | # Add all standard c-extensions to extension_modules list. 72 | prefs['import_dynload_stdmods'] = True 73 | 74 | # If `True` modules with syntax errors are considered to be empty. 75 | # The default value is `False`; When `False` syntax errors raise 76 | # `rope.base.exceptions.ModuleSyntaxError` exception. 77 | prefs['ignore_syntax_errors'] = False 78 | 79 | # If `True`, rope ignores unresolvable imports. Otherwise, they 80 | # appear in the importing namespace. 81 | prefs['ignore_bad_imports'] = False 82 | 83 | # If `True`, rope will insert new module imports as 84 | # `from import ` by default. 85 | prefs['prefer_module_from_imports'] = False 86 | 87 | # If `True`, rope will transform a comma list of imports into 88 | # multiple separate import statements when organizing 89 | # imports. 90 | prefs['split_imports'] = False 91 | 92 | # If `True`, rope will remove all top-level import statements and 93 | # reinsert them at the top of the module when making changes. 94 | prefs['pull_imports_to_top'] = True 95 | 96 | # If `True`, rope will sort imports alphabetically by module name instead of 97 | # alphabetically by import statement, with from imports after normal 98 | # imports. 99 | prefs['sort_imports_alphabetically'] = False 100 | 101 | # Location of implementation of rope.base.oi.type_hinting.interfaces.ITypeHintingFactory 102 | # In general case, you don't have to change this value, unless you're an rope expert. 103 | # Change this value to inject you own implementations of interfaces 104 | # listed in module rope.base.oi.type_hinting.providers.interfaces 105 | # For example, you can add you own providers for Django Models, or disable the search 106 | # type-hinting in a class hierarchy, etc. 107 | prefs['type_hinting_factory'] = 'rope.base.oi.type_hinting.factory.default_type_hinting_factory' 108 | 109 | 110 | def project_opened(project): 111 | """This function is called after opening the project""" 112 | # Do whatever you like here! 113 | -------------------------------------------------------------------------------- /.vscode/.ropeproject/objectdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjaume/BPNeuralNetworks/ce8f859b03c452123e1c91179b7c9236f9bd0928/.vscode/.ropeproject/objectdb -------------------------------------------------------------------------------- /BPNN.py: -------------------------------------------------------------------------------- 1 | # encoding:utf-8 2 | 3 | ''' 4 | BP神经网络Python实现 5 | ''' 6 | 7 | import random 8 | import numpy as np; 9 | 10 | 11 | def sigmoid(x): 12 | ''' 13 | 激活函数 14 | ''' 15 | return 1.0 / (1.0 + np.exp(-x)) 16 | 17 | def sigmoid_prime(x): 18 | return sigmoid(x) * (1 - sigmoid(x)) 19 | 20 | class BPNNClassification: 21 | def __init__(self, sizes): 22 | 23 | # 神经网络结构 24 | self.num_layers = len(sizes) 25 | self.sizes = sizes 26 | 27 | # 初始化偏差,除输入层外, 其它每层每个节点都生成一个 biase 值(0-1) 28 | self.biases = [np.random.randn(n, 1) for n in sizes[1:]] 29 | # 随机生成每条神经元连接的 weight 值(0-1) 30 | self.weights = [np.random.randn(r, c) 31 | for c, r in zip(sizes[:-1], sizes[1:])] 32 | 33 | def feed_forward(self, a): 34 | ''' 35 | 前向传输计算输出神经元的值 36 | ''' 37 | for b, w in zip(self.biases, self.weights): 38 | a = sigmoid(np.dot(w, a) + b) 39 | return a 40 | 41 | def MSGD(self, training_data, epochs, mini_batch_size, eta, test_data=None): 42 | ''' 43 | 小批量随机梯度下降法 44 | ''' 45 | if test_data: n_test = len(test_data) 46 | n = len(training_data) 47 | for j in xrange(epochs): 48 | # 随机打乱训练集顺序 49 | random.shuffle(training_data) 50 | # 根据小样本大小划分子训练集集合 51 | mini_batchs = [training_data[k:k+mini_batch_size] 52 | for k in xrange(0, n, mini_batch_size)] 53 | # 利用每一个小样本训练集更新 w 和 b 54 | for mini_batch in mini_batchs: 55 | self.updata_WB_by_mini_batch(mini_batch, eta) 56 | 57 | #迭代一次后结果 58 | if test_data: 59 | print("Epoch {0}: {1} / {2}".format(j, self.evaluate(test_data), n_test)) 60 | else: 61 | print("Epoch {0}".format(j)) 62 | 63 | def updata_WB_by_mini_batch(self, mini_batch, eta): 64 | ''' 65 | 利用小样本训练集更新 w 和 b 66 | mini_batch: 小样本训练集 67 | eta: 学习率 68 | ''' 69 | # 创建存储迭代小样本得到的 b 和 w 偏导数空矩阵,大小与 biases 和 weights 一致,初始值为 0 70 | batch_par_b = [np.zeros(b.shape) for b in self.biases] 71 | batch_par_w = [np.zeros(w.shape) for w in self.weights] 72 | 73 | for x, y in mini_batch: 74 | # 根据小样本中每个样本的输入 x, 输出 y, 计算 w 和 b 的偏导 75 | delta_b, delta_w = self.back_propagation(x, y) 76 | # 累加偏导 delta_b, delta_w 77 | batch_par_b = [bb + dbb for bb, dbb in zip(batch_par_b, delta_b)] 78 | batch_par_w = [bw + dbw for bw, dbw in zip(batch_par_w, delta_w)] 79 | # 根据累加的偏导值 delta_b, delta_w 更新 b, w 80 | # 由于用了小样本,因此 eta 需除以小样本长度 81 | self.weights = [w - (eta / len(mini_batch)) * dw 82 | for w, dw in zip(self.weights, batch_par_w)] 83 | self.biases = [b - (eta / len(mini_batch)) * db 84 | for b, db in zip(self.biases, batch_par_b)] 85 | 86 | def back_propagation(self, x, y): 87 | ''' 88 | 利用误差后向传播算法对每个样本求解其 w 和 b 的更新量 89 | x: 输入神经元,行向量 90 | y: 输出神经元,行向量 91 | ''' 92 | delta_b = [np.zeros(b.shape) for b in self.biases] 93 | delta_w = [np.zeros(w.shape) for w in self.weights] 94 | 95 | # 前向传播,求得输出神经元的值 96 | a = x # 神经元输出值 97 | # 存储每个神经元输出 98 | activations = [x] 99 | # 存储经过 sigmoid 函数计算的神经元的输入值,输入神经元除外 100 | zs = [] 101 | for b, w in zip(self.biases, self.weights): 102 | z = np.dot(w, a) + b 103 | zs.append(z) 104 | a = sigmoid(z) # 输出神经元 105 | activations.append(a) 106 | 107 | # 求解输出层δ 108 | delta = self.cost_function(activations[-1], y) * sigmoid_prime(zs[-1]) 109 | delta_b[-1] = delta 110 | delta_w[-1] = np.dot(delta, activations[-2].T) 111 | for lev in xrange(2, self.num_layers): 112 | # 从倒数第1层开始更新,因此需要采用-lev 113 | # 利用 lev + 1 层的 δ 计算 l 层的 δ 114 | z = zs[-lev] 115 | zp = sigmoid_prime(z) 116 | delta = np.dot(self.weights[-lev+1].T, delta) * zp 117 | delta_b[-lev] = delta 118 | delta_w[-lev] = np.dot(delta, activations[-lev-1].T) 119 | return (delta_b, delta_w) 120 | 121 | def evaluate(self, test_data): 122 | test_result = [(np.argmax(self.feed_forward(x)), y) 123 | for (x, y) in test_data] 124 | return sum(int(x == y) for (x, y) in test_result) 125 | 126 | def predict(self, test_input): 127 | test_result = [self.feed_forward(x) 128 | for x in test_input] 129 | return test_result 130 | 131 | def cost_function(self, output_a, y): 132 | ''' 133 | 损失函数 134 | ''' 135 | return (output_a - y) 136 | 137 | class BPNNRegression: 138 | ''' 139 | 神经网络回归与分类的差别在于: 140 | 1. 输出层不需要再经过激活函数 141 | 2. 输出层的 w 和 b 更新量计算相应更改 142 | ''' 143 | def __init__(self, sizes): 144 | 145 | # 神经网络结构 146 | self.num_layers = len(sizes) 147 | self.sizes = sizes 148 | 149 | # 初始化偏差,除输入层外, 其它每层每个节点都生成一个 biase 值(0-1) 150 | self.biases = [np.random.randn(n, 1) for n in sizes[1:]] 151 | # 随机生成每条神经元连接的 weight 值(0-1) 152 | self.weights = [np.random.randn(r, c) 153 | for c, r in zip(sizes[:-1], sizes[1:])] 154 | 155 | def feed_forward(self, a): 156 | ''' 157 | 前向传输计算输出神经元的值 158 | ''' 159 | for i, b, w in zip(range(len(self.biases)), self.biases, self.weights): 160 | # 输出神经元不需要经过激励函数 161 | if i == len(self.biases) - 1: 162 | a = np.dot(w, a) + b 163 | break 164 | a = sigmoid(np.dot(w, a) + b) 165 | return a 166 | 167 | def MSGD(self, training_data, epochs, mini_batch_size, eta, error = 0.01): 168 | ''' 169 | 小批量随机梯度下降法 170 | ''' 171 | n = len(training_data) 172 | for j in xrange(epochs): 173 | # 随机打乱训练集顺序 174 | random.shuffle(training_data) 175 | # 根据小样本大小划分子训练集集合 176 | mini_batchs = [training_data[k:k+mini_batch_size] 177 | for k in xrange(0, n, mini_batch_size)] 178 | # 利用每一个小样本训练集更新 w 和 b 179 | for mini_batch in mini_batchs: 180 | self.updata_WB_by_mini_batch(mini_batch, eta) 181 | 182 | #迭代一次后结果 183 | err_epoch = self.evaluate(training_data) 184 | print("Epoch {0} Error {1}".format(j, err_epoch)) 185 | if err_epoch < error: 186 | break; 187 | # if test_data: 188 | # print("Epoch {0}: {1} / {2}".format(j, self.evaluate(test_data), n_test)) 189 | # else: 190 | # print("Epoch {0}".format(j)) 191 | return err_epoch 192 | 193 | def updata_WB_by_mini_batch(self, mini_batch, eta): 194 | ''' 195 | 利用小样本训练集更新 w 和 b 196 | mini_batch: 小样本训练集 197 | eta: 学习率 198 | ''' 199 | # 创建存储迭代小样本得到的 b 和 w 偏导数空矩阵,大小与 biases 和 weights 一致,初始值为 0 200 | batch_par_b = [np.zeros(b.shape) for b in self.biases] 201 | batch_par_w = [np.zeros(w.shape) for w in self.weights] 202 | 203 | for x, y in mini_batch: 204 | # 根据小样本中每个样本的输入 x, 输出 y, 计算 w 和 b 的偏导 205 | delta_b, delta_w = self.back_propagation(x, y) 206 | # 累加偏导 delta_b, delta_w 207 | batch_par_b = [bb + dbb for bb, dbb in zip(batch_par_b, delta_b)] 208 | batch_par_w = [bw + dbw for bw, dbw in zip(batch_par_w, delta_w)] 209 | # 根据累加的偏导值 delta_b, delta_w 更新 b, w 210 | # 由于用了小样本,因此 eta 需除以小样本长度 211 | self.weights = [w - (eta / len(mini_batch)) * dw 212 | for w, dw in zip(self.weights, batch_par_w)] 213 | self.biases = [b - (eta / len(mini_batch)) * db 214 | for b, db in zip(self.biases, batch_par_b)] 215 | 216 | def back_propagation(self, x, y): 217 | ''' 218 | 利用误差后向传播算法对每个样本求解其 w 和 b 的更新量 219 | x: 输入神经元,行向量 220 | y: 输出神经元,行向量 221 | 222 | ''' 223 | delta_b = [np.zeros(b.shape) for b in self.biases] 224 | delta_w = [np.zeros(w.shape) for w in self.weights] 225 | 226 | # 前向传播,求得输出神经元的值 227 | a = x # 神经元输出值 228 | # 存储每个神经元输出 229 | activations = [x] 230 | # 存储经过 sigmoid 函数计算的神经元的输入值,输入神经元除外 231 | zs = [] 232 | for b, w in zip(self.biases, self.weights): 233 | z = np.dot(w, a) + b 234 | zs.append(z) 235 | a = sigmoid(z) # 输出神经元 236 | activations.append(a) 237 | #------------- 238 | activations[-1] = zs[-1] # 更改神经元输出结果 239 | #------------- 240 | # 求解输出层δ 241 | # 与分类问题不同,Delta计算不需要乘以神经元输入的倒数 242 | #delta = self.cost_function(activations[-1], y) * sigmoid_prime(zs[-1]) 243 | delta = self.cost_function(activations[-1], y) #更改后 244 | #------------- 245 | delta_b[-1] = delta 246 | delta_w[-1] = np.dot(delta, activations[-2].T) 247 | for lev in xrange(2, self.num_layers): 248 | # 从倒数第1层开始更新,因此需要采用-lev 249 | # 利用 lev + 1 层的 δ 计算 l 层的 δ 250 | z = zs[-lev] 251 | zp = sigmoid_prime(z) 252 | delta = np.dot(self.weights[-lev+1].T, delta) * zp 253 | delta_b[-lev] = delta 254 | delta_w[-lev] = np.dot(delta, activations[-lev-1].T) 255 | return (delta_b, delta_w) 256 | 257 | def evaluate(self, train_data): 258 | test_result = [[self.feed_forward(x), y] 259 | for x, y in train_data] 260 | return np.sum([0.5 * (x - y) ** 2 for (x, y) in test_result]) 261 | 262 | def predict(self, test_input): 263 | test_result = [self.feed_forward(x) 264 | for x in test_input] 265 | return test_result 266 | 267 | def cost_function(self, output_a, y): 268 | ''' 269 | 损失函数 270 | ''' 271 | return (output_a - y) 272 | pass -------------------------------------------------------------------------------- /BPNN.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjaume/BPNeuralNetworks/ce8f859b03c452123e1c91179b7c9236f9bd0928/BPNN.pyc -------------------------------------------------------------------------------- /DoubanRateLoader.py: -------------------------------------------------------------------------------- 1 | # encoding:utf-8 2 | 3 | ''' 4 | 获取豆瓣评论数据集 5 | ''' 6 | 7 | import numpy as np 8 | 9 | data_file = 'douban_rate.csv' 10 | 11 | def load_data_for_regresstion(): 12 | interval = 100 13 | data_set = np.loadtxt(data_file, dtype=float, delimiter=',') 14 | train_input = data_set[::interval,:-2] 15 | train_output = data_set[::interval, -2] 16 | train_data = [[sx.reshape(5,1), sy.reshape(1,1)] for sx, sy in zip (train_input, train_output)] 17 | return train_data 18 | 19 | def load_data(): 20 | data_set = np.loadtxt(data_file, dtype=float, delimiter=',') 21 | np.random.seed(1) 22 | train_data = data_set[:50000] 23 | test_data = data_set[50000:60000] 24 | train_data_r = get_train_data(train_data) 25 | test_data_r = get_test_data(test_data) 26 | return (train_data_r, test_data_r) 27 | 28 | def get_train_data(train_data): 29 | train_x , train_y = train_data[:, :-2], train_data[:, -1] 30 | train_x_r = [x.reshape(len(x), 1) for x in train_x] 31 | train_y_r = [np.array([[1 if y==0 else 0], 32 | [1 if y==1 else 0], 33 | [1 if y==2 else 0], 34 | [1 if y==3 else 0]]) 35 | for y in train_y] 36 | train_data_r = [[x, y] for x, y in zip(train_x_r, train_y_r)] 37 | return train_data_r 38 | 39 | def get_test_data(test_data): 40 | test_x , test_y = test_data[:, :-2], test_data[:, -1] 41 | test_x_r = [x.reshape(len(x), 1) for x in test_x] 42 | test_data_r = [[x, y] for x, y in zip(test_x_r, test_y)] 43 | return test_data_r 44 | -------------------------------------------------------------------------------- /DoubanRateLoader.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjaume/BPNeuralNetworks/ce8f859b03c452123e1c91179b7c9236f9bd0928/DoubanRateLoader.pyc -------------------------------------------------------------------------------- /GradientDescent.py: -------------------------------------------------------------------------------- 1 | # encoding:utf-8 2 | 3 | ''' 4 | 梯度下降算法 5 | ''' 6 | import numpy as np; 7 | 8 | test_result = [[np.array([[0.5]]), np.array([[0.3]])], 9 | [np.array([[0.5]]), np.array([[0.3]])], 10 | [np.array([[0.5]]), np.array([[0.3]])], 11 | ] 12 | t = [0.5 * (x - y) ** 2 for (x, y) in test_result] 13 | print np.sum(t) 14 | a = np.sum(0.5 * (x - y) ** 2 for (x, y) in test_result) 15 | 16 | print a 17 | if a > np.array([[0.04]]): 18 | print('ok') 19 | 20 | print np.sum([ 21 | np.array([[0.04]]), 22 | np.array([[0.04]]) 23 | ]) -------------------------------------------------------------------------------- /IrisDataSet.csv: -------------------------------------------------------------------------------- 1 | 5.8,4,1.2,0.2,0 2 | 5.7,4.4,1.5,0.4,0 3 | 5.4,3.9,1.3,0.4,0 4 | 5.1,3.5,1.4,0.3,0 5 | 5.7,3.8,1.7,0.3,0 6 | 5.1,3.8,1.5,0.3,0 7 | 5.4,3.4,1.7,0.2,0 8 | 5.1,3.7,1.5,0.4,0 9 | 4.6,3.6,1,0.2,0 10 | 5.1,3.3,1.7,0.5,0 11 | 4.8,3.4,1.9,0.2,0 12 | 5,3,1.6,0.2,0 13 | 5,3.4,1.6,0.4,0 14 | 5.2,3.5,1.5,0.2,0 15 | 5.2,3.4,1.4,0.2,0 16 | 4.7,3.2,1.6,0.2,0 17 | 4.8,3.1,1.6,0.2,0 18 | 5.4,3.4,1.5,0.4,0 19 | 5.2,4.1,1.5,0.1,0 20 | 5.5,4.2,1.4,0.2,0 21 | 4.9,3.1,1.5,0.2,0 22 | 5,3.2,1.2,0.2,0 23 | 5.5,3.5,1.3,0.2,0 24 | 4.9,3.6,1.4,0.1,0 25 | 4.4,3,1.3,0.2,0 26 | 5.1,3.4,1.5,0.2,0 27 | 5,3.5,1.3,0.3,0 28 | 4.5,2.3,1.3,0.3,0 29 | 4.4,3.2,1.3,0.2,0 30 | 5,3.5,1.6,0.6,0 31 | 5.1,3.8,1.9,0.4,0 32 | 4.8,3,1.4,0.3,0 33 | 5.1,3.8,1.6,0.2,0 34 | 4.6,3.2,1.4,0.2,0 35 | 5.3,3.7,1.5,0.2,0 36 | 5,3.3,1.4,0.2,0 37 | 7,3.2,4.7,1.4,1 38 | 6.4,3.2,4.5,1.5,1 39 | 6.9,3.1,4.9,1.5,1 40 | 5.5,2.3,4,1.3,1 41 | 6.3,3.3,4.7,1.6,1 42 | 4.9,2.4,3.3,1,1 43 | 6.6,2.9,4.6,1.3,1 44 | 5.2,2.7,3.9,1.4,1 45 | 5,2,3.5,1,1 46 | 5.9,3,4.2,1.5,1 47 | 6,2.2,4,1,1 48 | 6.7,3,5,1.7,1 49 | 6,2.9,4.5,1.5,1 50 | 5.7,2.6,3.5,1,1 51 | 5.5,2.4,3.8,1.1,1 52 | 5.5,2.4,3.7,1,1 53 | 5.8,2.7,3.9,1.2,1 54 | 6,2.7,5.1,1.6,1 55 | 5.4,3,4.5,1.5,1 56 | 6,3.4,4.5,1.6,1 57 | 6.7,3.1,4.7,1.5,1 58 | 6.3,2.3,4.4,1.3,1 59 | 5.6,3,4.1,1.3,1 60 | 5.5,2.5,4,1.3,1 61 | 5.5,2.6,4.4,1.2,1 62 | 6.1,3,4.6,1.4,1 63 | 5.8,2.6,4,1.2,1 64 | 5,2.3,3.3,1,1 65 | 6.1,2.9,4.7,1.4,1 66 | 5.6,2.9,3.6,1.3,1 67 | 6.7,3.1,4.4,1.4,1 68 | 5.6,3,4.5,1.5,1 69 | 5.8,2.7,4.1,1,1 70 | 6.2,2.2,4.5,1.5,1 71 | 5.6,2.5,3.9,1.1,1 72 | 5.9,3.2,4.8,1.8,1 73 | 6.1,2.8,4,1.3,1 74 | 6.3,2.5,4.9,1.5,1 75 | 6.1,2.8,4.7,1.2,1 76 | 6.4,2.9,4.3,1.3,1 77 | 6.6,3,4.4,1.4,1 78 | 6.8,2.8,4.8,1.4,1 79 | 6.5,3.2,5.1,2,2 80 | 6.8,3,5.5,2.1,2 81 | 5.7,2.5,5,2,2 82 | 5.8,2.8,5.1,2.4,2 83 | 6.4,3.2,5.3,2.3,2 84 | 6.5,3,5.5,1.8,2 85 | 7.7,3.8,6.7,2.2,2 86 | 7.7,2.6,6.9,2.3,2 87 | 6,2.2,5,1.5,2 88 | 6.9,3.2,5.7,2.3,2 89 | 5.6,2.8,4.9,2,2 90 | 7.7,2.8,6.7,2,2 91 | 6.3,2.7,4.9,1.8,2 92 | 6.7,3.3,5.7,2.1,2 93 | 7.2,3.2,6,1.8,2 94 | 6.2,2.8,4.8,1.8,2 95 | 6.1,3,4.9,1.8,2 96 | 6.4,2.8,5.6,2.1,2 97 | 7.2,3,5.8,1.6,2 98 | 7.6,3,6.6,2.1,2 99 | 4.9,2.5,4.5,1.7,2 100 | 7.3,2.9,6.3,1.8,2 101 | 6.7,2.5,5.8,1.8,2 102 | 7.2,3.6,6.1,2.5,2 103 | 7.4,2.8,6.1,1.9,2 104 | 7.9,3.8,6.4,2,2 105 | 6.4,2.8,5.6,2.2,2 106 | 6.3,2.8,5.1,1.5,2 107 | 6.1,2.6,5.6,1.4,2 108 | 7.7,3,6.1,2.3,2 109 | 6.3,3.4,5.6,2.4,2 110 | 6.4,3.1,5.5,1.8,2 111 | 6,3,4.8,1.8,2 112 | 6.9,3.1,5.4,2.1,2 113 | 6.7,3.1,5.6,2.4,2 114 | 6.9,3.1,5.1,2.3,2 115 | 5.8,2.7,5.1,1.9,2 116 | 6.8,3.2,5.9,2.3,2 117 | 6.7,3.3,5.7,2.5,2 118 | 6.7,3,5.2,2.3,2 119 | 6.3,2.5,5,1.9,2 120 | 6.5,3,5.2,2,2 121 | 6.2,3.4,5.4,2.3,2 122 | 5.9,3,5.1,1.8,2 123 | 5.1,3.5,1.4,0.2,0 124 | 6.5,2.8,4.6,1.5,1 125 | 5.7,2.8,4.5,1.3,1 126 | 6.4,2.7,5.3,1.9,2 127 | 4.9,3,1.4,0.2,0 128 | 4.7,3.2,1.3,0.2,0 129 | 4.6,3.1,1.5,0.2,0 130 | 5,3.6,1.4,0.2,0 131 | 5.4,3.9,1.7,0.4,0 132 | 4.6,3.4,1.4,0.3,0 133 | 5,3.4,1.5,0.2,0 134 | 4.4,2.9,1.4,0.2,0 135 | 4.9,3.1,1.5,0.1,0 136 | 5.4,3.7,1.5,0.2,0 137 | 4.8,3.4,1.6,0.2,0 138 | 4.8,3,1.4,0.1,0 139 | 4.3,3,1.1,0.1,0 140 | 5.6,2.7,4.2,1.3,1 141 | 5.7,3,4.2,1.2,1 142 | 5.7,2.9,4.2,1.3,1 143 | 6.2,2.9,4.3,1.3,1 144 | 5.1,2.5,3,1.1,1 145 | 5.7,2.8,4.1,1.3,1 146 | 6.3,3.3,6,2.5,2 147 | 5.8,2.7,5.1,1.9,2 148 | 7.1,3,5.9,2.1,2 149 | 6.3,2.9,5.6,1.8,2 150 | 6.5,3,5.8,2.2,2 151 | 152 | -------------------------------------------------------------------------------- /IrisLoader.py: -------------------------------------------------------------------------------- 1 | # encoding:utf-8 2 | 3 | ''' 4 | 获取数据集,包括训练集以及测试集 5 | ''' 6 | 7 | import numpy as np 8 | import os 9 | 10 | data_file = 'IrisDataSet.csv' 11 | def load_data(): 12 | if not os.path.exists(data_file): 13 | raise IOError(u'文件不存在') 14 | data_set = np.loadtxt(data_file, dtype=float, delimiter=',') 15 | np.random.seed(1) 16 | train_data = data_set[:-30] 17 | test_data = data_set[-30:] 18 | train_data_r = get_train_data(train_data) 19 | test_data_r = get_test_data(test_data) 20 | return (train_data_r, test_data_r) 21 | 22 | def get_train_data(train_data): 23 | train_x , train_y = train_data[:, :-1], train_data[:, -1] 24 | train_x_r = [x.reshape(len(x), 1) for x in train_x] 25 | train_y_r = [np.array([[1 if y==0 else 0], 26 | [1 if y==1 else 0], 27 | [1 if y==2 else 0]]) 28 | for y in train_y] 29 | train_data_r = [[x, y] for x, y in zip(train_x_r, train_y_r)] 30 | return train_data_r 31 | 32 | def get_test_data(test_data): 33 | test_x , test_y = test_data[:, :-1], test_data[:, -1] 34 | test_x_r = [x.reshape(len(x), 1) for x in test_x] 35 | test_data_r = [[x, y] for x, y in zip(test_x_r, test_y)] 36 | return test_data_r 37 | 38 | # train_data_r, test_data_r = load_data() 39 | # print test_data_r[0] 40 | -------------------------------------------------------------------------------- /IrisLoader.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tjaume/BPNeuralNetworks/ce8f859b03c452123e1c91179b7c9236f9bd0928/IrisLoader.pyc -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # BP神经网络原理及其Python实现 2 | 代码分为两个部分,其一是BP神经网络分类,其二是BP神经网络回归 3 | 4 | ## 分类 5 | 6 | ### 实例1 7 | 采用费雪鸢尾花卉数据作为测试数据集,150个样本数据,三类数据:分别是山鸢尾、变色鸢尾和维吉尼亚鸢尾。 8 | 9 | 数据集代码如下: 10 | 11 | 山鸢尾:0 12 | 变色鸢尾:1 13 | 维吉尼亚鸢尾:2 14 | 15 | 采用前120个作为训练样本,后30个作为测试样本 16 | 17 | ### 实例2 18 | 19 | 将豆瓣读书5个评分等级作为输入,总评分作为输出,利用5万本书进行训练,1万本书作为测试样本。 20 | 21 | ## 回归 22 | 23 | 拟合多项式 24 | 25 | -------------------------------------------------------------------------------- /test_classification.py: -------------------------------------------------------------------------------- 1 | #encoding:utf-8 2 | 3 | from network import Network 4 | from BPNN import BPNNClassification 5 | import IrisLoader 6 | import DoubanRateLoader 7 | 8 | def test1(): 9 | train_data, test_data = IrisLoader.load_data() 10 | # bp = Network([4, 15, 3]) 11 | # bp.SGD(train_data, 10000, 10, 0.5, test_data=test_data) 12 | 13 | bp1 = BPNNClassification([4, 15, 3]) 14 | bp1.MSGD(train_data, 10000, 10, 0.5, test_data=test_data) 15 | 16 | def test2(): 17 | train_data, test_data = DoubanRateLoader.load_data() 18 | # bp = Network([4, 15, 3]) 19 | # bp.SGD(train_data, 10000, 10, 0.5, test_data=test_data) 20 | 21 | bp1 = BPNNClassification([5, 15, 4]) 22 | bp1.MSGD(train_data, 200, 30, 0.3, test_data=test_data) 23 | 24 | test2() -------------------------------------------------------------------------------- /test_regression.py: -------------------------------------------------------------------------------- 1 | # encoding:utf-8 2 | ''' 3 | BP神经网络回归测试 4 | ''' 5 | 6 | import BPNN 7 | import numpy as np 8 | import DoubanRateLoader 9 | 10 | #一元二次多项式 11 | def oneQua(x): 12 | return 2 * x ** 2 + 3 * x + 5 13 | 14 | def get_train_data(): 15 | x = np.linspace(-3.5, 3.5, 50) 16 | y = oneQua(x) 17 | train_data = [[sx.reshape(1,1), sy.reshape(1,1)] for sx, sy in zip(x, y)] 18 | return train_data 19 | 20 | def get_test_data(): 21 | x = np.array([-3.7, 2.6, 1.3, 0.3, -2.5]) 22 | y = oneQua(x) 23 | test_data = [np.reshape(sx, (1,1)) for sx in x] 24 | print test_data 25 | return test_data, y 26 | 27 | def test1(): 28 | ''' 29 | 多项式预测 30 | ''' 31 | bp1 = BPNN.BPNNRegression([1, 20, 1]) 32 | 33 | train_data = get_train_data() 34 | test_data, y = get_test_data() 35 | 36 | bp1.MSGD(train_data, 10000, 8, 0.2) 37 | print y 38 | print bp1.predict(test_data) 39 | 40 | def test2(): 41 | train_data = DoubanRateLoader.load_data_for_regresstion() 42 | bp = BPNN.BPNNRegression([5, 7, 1]) 43 | err_arr = [] 44 | for rate in [0.1, 0.2, 0.4, 0.5, 0.6, 0.9]: 45 | err_arr.append(bp.MSGD(train_data, 10000, len(train_data), 0.3)) 46 | break 47 | print err_arr 48 | 49 | test2() 50 | 51 | --------------------------------------------------------------------------------