Python——numpy实现简单BP神经网络识别手写数字

识别结果

数据集:

链接:https://pan.baidu.com/s/1XzexzXGYhUdFpM4UaIb3yA
提取码:9wjm

代码:

1.核心代码:神经网络以及BP算法
import numpy as np
from tqdm import trange	# 替换range()可实现动态进度条,可忽略


def sigmoid(x): # 激活函数采用Sigmoid
    return 1 / (1 + np.exp(-x))


def sigmoid_derivative(x):	# Sigmoid的导数
    return sigmoid(x) * (1 - sigmoid(x))


class NeuralNetwork:	# 神经网络
    def __init__(self, layers):	# layers为神经元个数列表
        self.activation = sigmoid	# 激活函数
        self.activation_deriv = sigmoid_derivative	# 激活函数导数
        self.weights = []	# 权重列表
        self.bias = []	# 偏置列表
        for i in range(1, len(layers)):	# 正态分布初始化
            self.weights.append(np.random.randn(layers[i-1], layers[i]))
            self.bias.append(np.random.randn(layers[i]))

    def fit(self, x, y, learning_rate=0.2, epochs=3):	# 反向传播算法
        x = np.atleast_2d(x)
        n = len(y)	# 样本数
        p = max(n, epochs)	# 样本过少时根据epochs减半学习率
        y = np.array(y)

        for k in trange(epochs * n):	# 带进度条的训练过程
            if (k+1) % p == 0:
                learning_rate *= 0.5	# 每训练完一代样本减半学习率
            a = [x[k % n]]	# 保存各层激活值的列表
            # 正向传播开始
            for lay in range(len(self.weights)):
                a.append(self.activation(np.dot(a[lay], self.weights[lay]) + self.bias[lay]))
            # 反向传播开始
            label = np.zeros(a[-1].shape)
            label[y[k % n]] = 1	# 根据类号生成标签
            error = label - a[-1]	# 误差值
            deltas = [error * self.activation_deriv(a[-1])]	# 保存各层误差值的列表

            layer_num = len(a) - 2	# 导数第二层开始
            for j in range(layer_num, 0, -1):
                deltas.append(deltas[-1].dot(self.weights[j].T) * self.activation_deriv(a[j]))	# 误差的反向传播
            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)
                self.bias[i] += learning_rate * deltas[i]

    def predict(self, x):	# 预测
        a = np.array(x, dtype=np.float)
        for lay in range(0, len(self.weights)):	# 正向传播
            a = self.activation(np.dot(a, self.weights[lay]) + self.bias[lay])
        a = list(100 * a/sum(a))	# 改为百分比显示
        i = a.index(max(a))	# 预测值
        per = []	# 各类的置信程度
        for num in a:
            per.append(str(round(num, 2))+'%')
        return i, per

2.训练
from NeuralNetwork import NeuralNetwork
import numpy as np
import pickle
import csv


def train():
    file_name = 'data/train.csv'	# 数据集为42000张带标签的28x28手写数字图像
    y = []
    x = []
    y_t = []
    x_t = []
    with open(file_name, 'r') as f:
        reader = csv.reader(f)
        header_row = next(reader)
        print(header_row)
        for row in reader:
            if np.random.random() < 0.8:	# 大约80%的数据用于训练
                y.append(int(row[0]))
                x.append(list(map(int, row[1:])))
            else:
                y_t.append(int(row[0]))
                x_t.append(list(map(int, row[1:])))
    len_train = len(y)
    len_test = len(y_t)
    print('训练集大小%d,测试集大小%d' % (len_train, len_test))
    x = np.array(x)
    y = np.array(y)
    nn = NeuralNetwork([784, 784, 10])	# 神经网络各层神经元个数
    nn.fit(x, y)
    file = open('NN.txt', 'wb')
    pickle.dump(nn, file)
    count = 0
    for i in range(len_test):
        p, _ = nn.predict(x_t[i])
        if p == y_t[i]:
            count += 1
    print('模型识别正确率:', count/len_test)


def mini_test():	# 小型测试,验证神经网络能正常运行
    x = [[0, 0], [0, 1], [1, 0], [1, 1]]
    y = [0, 1, 2, 3]
    nn = NeuralNetwork([2, 4, 16, 4])
    nn.fit(x, y, epochs=10000)
    for i in x:
        print(nn.predict(i))


# mini_test()
train()

运行结果:

  • [ 784 , 784 , 10 ] [784,784,10] [784,784,10]
    [784,784,10]
  • [ 784 , 1568 , 10 ] [784,1568,10] [784,1568,10]
    [784,1568,10]
  • [ 784 , 784 , 784 , 10 ] [784,784,784,10] [784,784,784,10]
    [784,784,784,10]
  • [ 784 , 1568 , 1568 , 10 ] [784,1568,1568,10] [784,1568,1568,10]
    [784,1568,1568,10]
    可以发现提高神经网络规模几乎无法提高正确率,但如果加入正则化的话应该能进一步提高正确率。
3.测试
import csv
import pickle
import numpy as np
from matplotlib import pyplot as plt


def diplay_test():	# 读取测试集,预测,画图
    file_name = 'data/test.csv'
    file = open('NN.txt', 'rb')
    nn = pickle.load(file)
    with open(file_name, 'r') as f:
        reader = csv.reader(f)
        header_row = next(reader)
        print(header_row)
        i = 0
        for row in reader:
            i += 1
            img = np.array(row, dtype=np.uint8)
            img = img.reshape(28, 28)
            plt.imshow(img, cmap='gray')
            pre, lst = nn.predict(row)
            plt.title(str(pre), fontsize=24)
            plt.axis('off')
            plt.savefig('img/img' + str(i) + '.png')


diplay_test()

运行结果:
图像
部分图片以及识别结果

  • 28
    点赞
  • 125
    收藏
    觉得还不错? 一键收藏
  • 86
    评论
### 回答1: BP神经网络是一种常用的人工神经网络,可以用于手写数字识别。在Python中,可以使用第三方库如TensorFlow、Keras、PyTorch等来实现BP神经网络。具体实现步骤包括:1.准备手写数字数据集;2.将数据集分为训练集和测试集;3.构建BP神经网络模型;4.训练模型;5.测试模型准确率。通过不断调整神经网络的参数和结构,可以提高手写数字识别的准确率。 ### 回答2: BP神经网络(BP neural network)是一种常用的人工神经网络算法,可以实现手写数字识别。在Python中,可以使用一些库来实现此功能,例如TensorFlow、PyTorch或Keras。 首先需要准备一个手写数字识别数据集,比如常用的MNIST数据集。该数据集包含了大量的手写数字图像和对应的标签。可以使用Python的相关库,如scikit-learn或TensorFlow提供的API,快速获取和加载这些数据。 接下来,需要搭建BP神经网络模型。可以使用上述库提供的各种API、类和函数来创建一个神经网络模型。可以选择不同的网络架构,比如使用多个隐藏层,每个隐藏层有不同的神经元数量。也可以根据实际情况设置不同的激活函数和损失函数,如ReLU、sigmoid或softmax等。 然后,使用训练集对模型进行训练。通过多次迭代,将输入的手写数字图像与其对应的输出标签进行比较,并通过反向传播算法不断调整模型的权重和偏置,以使模型的损失函数逐渐减小。 最后,使用测试集对训练好的模型进行测试和评估。将测试集中的手写数字图像输入到模型中,然后与对应的真实标签进行比较,计算模型的准确率和其他评估指标。 总结来说,使用Python中的相关库和算法,可以实现BP神经网络来进行手写数字识别。通过准备数据集、搭建模型、训练模型和评估模型的过程,可以实现高效准确地识别手写数字的功能。 ### 回答3: 实现手写数字识别的方法之一是使用BP神经网络BP神经网络是一种常见的人工神经网络,它通过反向传播算法来训练和优化网络参数。 在Python中,我们可以使用一些开源的深度学习库(如TensorFlow、Keras或PyTorch)来实现BP神经网络进行手写数字识别。 首先,需要准备一个包含大量手写数字的训练集和测试集。我们可以使用MNIST(Modified National Institute of Standards and Technology)数据集,它包含了60000个训练样本和10000个测试样本。 然后,我们可以使用Python中的深度学习库来创建和训练BP神经网络模型。下面是一个使用Keras库的示例代码: 1. 引入所需库: ```python import numpy as np from keras.models import Sequential from keras.layers import Dense from keras.datasets import mnist ``` 2. 加载和预处理数据集: ```python (x_train, y_train), (x_test, y_test) = mnist.load_data() x_train = x_train.reshape(x_train.shape[0], 784).astype('float32') / 255 x_test = x_test.reshape(x_test.shape[0], 784).astype('float32') / 255 y_train = np_utils.to_categorical(y_train) y_test = np_utils.to_categorical(y_test) ``` 3. 构建神经网络模型: ```python model = Sequential() model.add(Dense(units=512, input_dim=784, activation='relu')) model.add(Dense(units=512, activation='relu')) model.add(Dense(units=10, activation='softmax')) ``` 4. 编译和训练模型: ```python model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs=10, batch_size=128) ``` 5. 对新样本进行预测: ```python predictions = model.predict(x_test) ``` 以上是BP神经网络实现手写数字识别Python代码示例。在实际操作中,还可以进行模型调参、数据增强和模型评估等进一步优化措施。
评论 86
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值