神经网络简单理解

1.什么是神经网络?

先举个例子:找工作
在考虑入要不要接受一个岗位,需要综合的考虑一些因素,比如:薪资,气氛,工作环境,离家远近等等,但是一个岗位不太可能所以的条件都满足,需要有些取舍。

怎么取舍呢?

当然是根据重要程度来,比如薪资肯定比气氛重要吧,
重要程度如何衡量?我们可以想到用权重表表示重要程度,权重越大表示越重要,权重越小表示越不重要

每个因素达到预期情况下,对结果的重要程度用如下权重表示

薪资: 0.5
气氛: 0.3
工作环境: 0.2
离家距离: 0.1

假设当这些因素加起来总权重大于0.6时就接受,有两种情况

1.薪资不错+(气氛,工作环境,距离三张至少满足一个)
2.薪资不行+(气氛,工作环境,距离三个都满足要求)

这些情况可以用下图表示:
这里写图片描述

中间的圆圈表示判断逻辑:当4个输入值的总和大于0.6输出1,小于0.6输出0

跟神经网络有什么关系呢?

神经网络有N个节点组成,每个节点跟上面判断单元一样,有输入端,逻辑处理,输出端组成,如下图所示
这里写图片描述

几个性质:

  • 1.神经网络至少有3层,从左到有分别是 输入层,隐藏层,输出层
  • 2.上面节点之前的连线代表权重,每条连线的权重值都是不一样的
  • 3.每层的每个节点与上层的所有节点都相连,所以又叫做全连接神经网络
神经网络有什么作用呢?

上面我们假定了每个因素的重要程度,但是现实是我们只有一堆历史数据,要根据历史数据来计算每个输入的权重,也就是我们所说的调参,有了这些参数后对于每个输入在通过计算后就可以预测结果了

为啥神经网络能起作用?

我们经常能听到“历史总是惊人的相识”这句话,从侧面也能反应事情凡事都是有一定规律的,神经网络通过多层,多参数能找到这种规律

怎么衡量神经网络模型好坏?

预测结果和实际结果比较,统计差距,差距小说明越好,差距越大说明越差

实际案例:手写数字分类
# coding: utf-8
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer
from sklearn.metrics import confusion_matrix, classification_report




def logistic(x):
    return 1.0 / (1 + np.exp(-x))

def logistic_deriv(x):
    """
    逻辑函数的导数
    """
    fx = logistic(x)
    return fx * (1 - fx)

class NeuralNetwork(object):
    def __init__(self, layers, activation='logistic'):
        """
        :param layers: 层数,如[4, 3, 2] 表示两层len(list)-1,(因为第一层是输入层,,有4个单元),
        第一层有3个单元,第二层有2个单元
        :param activation:
        """
        if activation == 'tanh':
            self.activation = tanh
            self.activation_deriv = tanh_deriv
        elif activation == 'logistic':
            self.activation = logistic
            self.activation_deriv = logistic_deriv

        # 初始化随即权重
        self.weights = []

        #np.random.random([4,3]) 生成第一层的权重,4*3的矩阵,列表示每个神经元的对应输入的权重权重

        for i in range(len(layers) - 1):
            #tmp = (np.random.random([layers[i], layers[i + 1]]) * 2 - 1) * 0.25
            tmp = (np.random.random([layers[i], layers[i + 1]]) * 2 - 1) * 0.25
            self.weights.append(tmp)
        # 偏向
        self.bias = []
        # 根据每层的个数来计算bias
        for i in range(1, len(layers)):
            self.bias.append((np.random.random(layers[i]) * 2 - 1) * 0.25)

    def fit(self, X, y, learning_rate=0.2, epochs=10000):
        X = np.atleast_2d(X)

        y = np.array(y)
        # 随即梯度
        for k in range(epochs):
            i = np.random.randint(X.shape[0])
            #i 表示第几个样本
            a = [X[i]]   # 随即取某一条实例
            #weights[j] 表示第j层的权重矩阵
            for j in range(len(self.weights)):
                #由于a是2维数组 所以a[0]就等于第一个样本的数据,第1层的权重是 64*100 的矩阵
                #得到第1层节点的输入值,遍历下来,得到第一个样本数值,中间N层的值,最后的输出值
                a.append(self.activation(np.dot(a[j], self.weights[j]) + self.bias[j] ))

            # a[-1] 表示最后的输出 one-hot 编码
            errors = y[i] - a[-1]
            #errors 比如 y[i]=[0 0 1 0 0 0 0 0 0 0 ] 第i个样本对应的是2,因为对应的下标是2
            #假设此时a[-1] = [0.2 0.3 0.4 0.2 0.3 0.4 0.5]
            #则对应的误差为y[i]-a[-1]=[-0.2 -0.3 0.6 ... 0.5]
            deltas = [errors * self.activation_deriv(a[-1]) ,]  # 输出层的误差
            # 反向传播,对于隐藏层的误差
            for j in range(len(a) - 2, 0, -1):
                tmp = np.dot(deltas[-1], self.weights[j].T) * self.activation_deriv(a[j])
                deltas.append(tmp)
            deltas.reverse()

            # 更新权重
            for j in range(len(self.weights)):
                layer = np.atleast_2d(a[j])
                delta = np.atleast_2d(deltas[j])
                #偏导*learning_rate

                self.weights[j] += learning_rate * np.dot(layer.T, delta)

            # 更新偏向
            for j in range(len(self.bias)):
                self.bias[j] += learning_rate * deltas[j]

    def predict(self, row):
        a = np.array(row) # 确保是 ndarray 对象
        for i in range(len(self.weights)):
            a = self.activation(np.dot(a, self.weights[i]) + self.bias[i])
        return a


if __name__ == "__main__":
    nn = NeuralNetwork(layers=[64, 100, 10])
    digits = datasets.load_digits()
    X = digits.data

    #1797个样本,每个样本64维,所以样本可以表示为 1797*64 的矩阵
    y = digits.target



    # 拆分为训练集和测试集
    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)


    nn.fit(X_train, labels_train)


    # 收集测试结果
    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))

猜你喜欢

转载自blog.csdn.net/lylclz/article/details/79835388