神经网络

来源:互联网 发布:2007excel数据有效性 编辑:程序博客网 时间:2024/06/06 03:45

一.理论篇

1.背景
以人脑中中的神经网络为启发,历史上有很多版本
最著名的算法是1980年的backpropagation
2.多层向前神经网络(Multilayer Feed-Forward Neural Network)
1)backpropagation被使用在多层先前神经网络上
2)输入层(input layer)、隐藏层(hidden layer)、输出层(output layer)
3)每层由单元组成
4)输入层是由训练集的特征向量来传入的
5)经过连接结点的权重传入下一层,一层的输出是下一层的输入
6)隐藏层的个数可以是任意的,输入输出层是一层
7)每个单元可以被称为神经结点,根据生物学来定义
8)在计算神经网络的层数时,输入层不考虑在内
9)一层中加权的求和,然后根据非线性方程转化输出
10)作为多层向前的神经网络,理论上,如果有足够多的隐藏层和足够大的训练集,可以模拟出任何方程;
3.设计神经网络结构
1)使用神经网络训练数据之前,必须确定神经网络的层数和每层的个数
2)特征向量在传入输入层时通常先标准化到0和1之间(为了加速学习过程)
3)离散型变量可以被编码成每一个输入单元对应一个特征向量可能赋的值
比如:特征值A可能取三个值(a0,a1,a2),可以使用三个输入单元来代表A
如果A=a0,那么代表a0的单元值就取1,其他取0
4)神经网络既可以用来解决分类问题,也可以解决回归问题
a.对于分类问题,如果是2类,可以用一个输出单元表示(0和1代表2类)
如果多余2类,每一个类别用一个输入单元表示
输入层的单元数量通常等于类别的数量
b.没有确定的规则来设计最好有多少个隐藏层
根据实验测试和误差,以及准确度来实验并改进
4.交叉验证方法(Cross-Validation)
K-fold cross validation
5.backpropagation算法
1)通过迭代性来处理训练集的实例
2)对比经过神经网络后输入层的预测值和真实值之间
3)反方向(从输出层-->隐藏层-->输入层)来以最小化误差来更新每个连接的权值
4)算法详细介绍
输入:D:数据集,I学习率,一个多层前向神经网络
输入:一个训练好的神经网络
初始化权重和偏差:随机初始化在-1到1之间,或者-0.5到0.5之间,每个单元有一个偏向
对于每一个训练实例X,执行以下步骤:
a.由输入层向前传递
b.根据误差反向传送
终止条件:
权值的跟新低于某个阀值
预测的错误率低于某个阀值
达到预定的循环次数

6.backpropagation(反向传播)算法举例

二.应用篇
1.关于非线性方程(non-linear transformation function)
sigmoid函数(S曲线)用来作为 activation function
1)双曲线函数(tanh)
2)逻辑函数(logistic function)

2.实现一个简单的神经网络算法

1)NN01.py(简单神经网络的定义实现)

# -*- coding: utf-8 -*-
import numpy as np
#更新权重使用的函数
#使用系统定义的双曲函数tanh函数
def tanh(x):
    return np.tanh(x)
#使用tanh的倒数,倒数的定义来源于其倒数的性质
def tanh_deriv(x):
    return 1.0 -np.tanh(x)*np.tanh(x)
#使用系统定义的双曲函数logistic函数
def logistic(x):
    return 1/(1+np.exp(-x))
#定义其倒数,倒数的定义来源于其倒数性质
def logistic_derivative(x):
    return logistic(x)*(1-logistic(x))


#面向对象的方法构造类
class NeuralNetwork:
    #定义构造函数,初始化权重
    #self:当前类的指针,等同于Java中的this
    #layers:一个列表,包含每层的数目
    #activation:默认为tanh
    def __init__(self,layers,activation="tanh"):
        #根据输入进行函数选择
        if activation == "logistic":
            self.activation = logistic
            self.activation_deriv = logistic_derivative
        elif activation == "tanh":
            self.activation = tanh
            self.activation_deriv = tanh_deriv
        #
        self.weights = []
        #它的之前层和之后层的权重
        for i in range(1,len(layers)-1):
            self.weights.append((2*np.random.random((layers[i - 1]+1,layers[i] + 1)) - 1)*0.25)
            self.weights.append((2*np.random.random((layers[i]+1,layers[i+1]+1))-1)*0.25)
    #根据不断迭代,更新模型
    #X:数据集
    #y:函数标记
    #learning_rate:学习率
    #epochs:循环次数
    def fit(self,X,y,learning_rate=0.2,epochs=10000):
        #X构造为二维矩阵
        X = np.atleast_2d(X)
        #初始化全为1的矩阵,多余列存储偏差
        temp = np.ones([X.shape[0],X.shape[1]+1])
        #最后一列为偏差,去除后赋值
        temp[:,0:-1] = X
        X = temp
        #列表转化为矩阵
        y = np.array(y)
        
        for k in range(epochs):
            #随机获取行数
            i = np.random.randint(X.shape[0])
            #X中随机选取一行进行更新
            a = [X[i]]
            #完成正向的所有更新
            #len(self.weights)等价于:神经网络层数
            for l in range(len(self.weights)):
                #dot为求内积,最终为内积求和
                a.append(self.activation(np.dot(a[l],self.weights[l])))
            #计算误差
            error = y[i]-a[-1]
            #更新之后的error
            deltas = [error*self.activation_deriv(a[-1])]
            #去掉最后一层和第一层
            for l in range(len(a)-2,0,-1):
                #更新隐藏层
                deltas.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] = x
        a = temp
        for l in range(0,len(self.weights)):
            a = self.activation(np.dot(a,self.weights[l]))
        return a

2)NN01-test.py(简单测试)
# -*- coding: utf-8 -*-
from NN01 import NeuralNetwork
import numpy as np
nn = 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))    

3)实验结果

[0, 0] [-0.00971222 -0.00970001]
[0, 1] [ 0.99865967  0.99865127]
[1, 0] [ 0.99857218  0.99856331]
[1, 1] [-0.01734052 -0.01732482]

4)结果分析

上述函数测试实现了:两个数值取异或运算

右侧的数据显示经过函数计算后的结果

3.手写数字的识别
图片:8*8

识别数字:0,1,2,3,4,5,6,7,8,9

1)HandwrittenDigitsRecognition.py(对测试数据进行预处理)

# -*- coding: utf-8 -*-
import numpy as np


from sklearn.datasets import load_digits#手写数字的类
from sklearn.metrics import confusion_matrix,classification_report#矩阵衡量结果
from sklearn.preprocessing import LabelBinarizer#数字转化为二维数据的格式
from NN01 import NeuralNetwork
from sklearn.cross_validation import train_test_split#交叉验证

#数据预处理
digits = load_digits()
X = digits.data
y = digits.target
X -= X.min()#数字需要标准化至0-1之间
X /= X.max()

#64:代表64个输入,特征值数量
#100:需要多余输入层
#10:结果分为10类
nn = NeuralNetwork([64,100,9],"logistic")#调用NeuralNetwork函数进行初始化
#原始数据分为测试集和训练集
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)#调用NeuralNetwork的函数进行数据的预测
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))

2)结果

start fitting
[[38  0  0 ...,  0  0  0]
 [ 0 40  0 ...,  0  0  2]
 [ 0  2 46 ...,  0  0  0]
 ..., 
 [ 0  0  0 ..., 46  0  0]
 [ 0  5  0 ...,  0 38  0]
 [ 0  0  0 ...,  0  1 40]]
             precision    recall  f1-score   support


          0       1.00      0.95      0.97        40
          1       0.73      0.95      0.82        42
          2       1.00      0.96      0.98        48
          3       1.00      0.88      0.94        42
          4       0.93      0.86      0.89        44
          5       0.88      0.98      0.92        44
          6       1.00      0.98      0.99        54
          7       0.98      1.00      0.99        46
          8       0.93      0.84      0.88        45
          9       0.93      0.89      0.91        45


avg / total       0.94      0.93      0.93       450

3)结果分析

对预测数据进行显示,给出每个数字的预测正确的概率




































原创粉丝点击