#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np#矩阵运算def tanh(x):return np.tanh(x)def tanh_deriv(x):#对tanh求导return 1.0 - np.tanh(x)*np.tanh(x)def logistic(x):#s函数return 1/(1 + np.exp(-x))def logistic_derivative(x):#对s函数求导return logistic(x)*(1-logistic(x))class NeuralNetwork:#面向对象定义一个神经网络类def __init__(self, layers, activation='tanh'):#下划线构造函数self 相当于本身这个类的指针 layer就是一个list 数字代表神经元个数""":param layers: A list containing the number of units in each layer.Should be at least two values:param activation: The activation function to be used. Can be"logistic" or "tanh""""if activation == 'logistic':self.activation = logistic#之前定义的s函数self.activation_deriv = logistic_derivative#求导函数elif activation == 'tanh':self.activation = tanh#双曲线函数self.activation_deriv = tanh_deriv#求导双曲线函数self.weights = []#初始化一个list作为 权重#初始化权重两个值之间随机初始化for i in range(1, len(layers) - 1):#有几层神经网络 除去输出层#i-1层 和i层之间的权重 随机生成layers[i - 1] + 1 * layers[i] + 1 的矩阵 -0.25-0.25self.weights.append((2*np.random.random((layers[i - 1] + 1, layers[i] + 1))-1)*0.25)#i层和i+1层之间的权重self.weights.append((2*np.random.random((layers[i] + 1, layers[i + 1]))-1)*0.25)def fit(self, X, y, learning_rate=0.2, epochs=10000):#训练神经网络#learning rateX = np.atleast_2d(X)#x至少2维temp = np.ones([X.shape[0], X.shape[1]+1])#初始化一个全为1的矩阵temp[:, 0:-1] = X # adding the bias unit to the input layerX = tempy = np.array(y)for k in range(epochs):i = np.random.randint(X.shape[0])#随机选行a = [X[i]]for l in range(len(self.weights)): #going forward network, for each layer#选择一条实例与权重点乘 并且将值传给激活函数,经过a的append 使得所有神经元都有了值(正向)a.append(self.activation(np.dot(a[l], self.weights[l]))) #Computer the node value for each layer (O_i) using activation functionerror = y[i] - a[-1] #Computer the error at the top layer 真实值与计算值的差(向量)#通过求导 得到权重应当调整的误差deltas = [error * self.activation_deriv(a[-1])] #For output layer, Err calculation (delta is updated error)#Staring backprobagation 更新weightfor l in range(len(a) - 2, 0, -1): # we need to begin at the second to last layer 每次减一#Compute the updated error (i,e, deltas) for each node going from top layer to input layerdeltas.append(deltas[-1].dot(self.weights[l].T)*self.activation_deriv(a[l]))deltas.reverse()for i in range(len(self.weights)):layer = np.atleast_2d(a[i])delta = np.atleast_2d(deltas[i])self.weights[i] += learning_rate * layer.T.dot(delta)def predict(self, x):x = np.array(x)temp = np.ones(x.shape[0]+1)temp[0:-1] = xa = tempfor l in range(0, len(self.weights)):a = self.activation(np.dot(a, self.weights[l]))return a
异或运算
from NeuralNetwork import NeuralNetwork
import numpy as npnn = NeuralNetwork([2, 2, 1], 'tanh')
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([0, 1, 1, 0])
nn.fit(X, y)
for i in [[0, 0], [0, 1], [1, 0], [1, 1]]:print(i, nn.predict(i))
([0, 0], array([-0.00475208]))
([0, 1], array([ 0.99828477]))
([1, 0], array([ 0.99827186]))
([1, 1], array([-0.00776711]))
手写体识别
#!/usr/bin/python
# -*- coding:utf-8 -*-# 每个图片8x8 识别数字:0,1,2,3,4,5,6,7,8,9import numpy as np
from sklearn.datasets import load_digits
from sklearn.metrics import confusion_matrix, classification_report
from sklearn.preprocessing import LabelBinarizer
from NeuralNetwork import NeuralNetwork
from sklearn.model_selection import train_test_splitdigits = load_digits()
X = digits.data
y = digits.target
X -= X.min() # normalize the values to bring them into the range 0-1
X /= X.max()nn = NeuralNetwork([64, 100, 10], 'logistic')
X_train, X_test, y_train, y_test = train_test_split(X, y)
labels_train = LabelBinarizer().fit_transform(y_train)
labels_test = LabelBinarizer().fit_transform(y_test)
print "start fitting"
nn.fit(X_train, labels_train, epochs=3000)
predictions = []
for i in range(X_test.shape[0]):o = nn.predict(X_test[i])predictions.append(np.argmax(o))
print confusion_matrix(y_test, predictions)
print classification_report(y_test, predictions)
confusion_matrix
precision recall f1-score support0 1.00 0.97 0.99 341 0.75 0.91 0.82 462 1.00 0.92 0.96 503 1.00 0.92 0.96 514 0.94 0.91 0.92 535 0.95 0.96 0.96 576 0.97 0.95 0.96 387 0.88 1.00 0.93 358 0.88 0.83 0.85 429 0.86 0.82 0.84 44avg / total 0.92 0.92 0.92 450