Python | BP算法_数字识别

Hello!这里是六个核桃Lu!

Python | BP算法_数字识别 

(代码在文末)

全部代码如下:

import pandas as pd
import numpy as np

# 数字0,5,1,6,2,7,3,8,4,9
X = np.array([
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0,
               0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,
               0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
               0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,
               0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0,
               0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0,
               0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0,
               0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0,
               0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0,
               0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
              [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0,
               0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
             ])

# 数字为0-9
Xtest = np.array([
                  [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1,
                   0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
                   0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1,
                   0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1,
                   0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0,
                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
                   0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0,
                   0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0,
                   0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
                   0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
                  [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1,
                   0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
                 ])
# 测试数据 横着数个数,0表示空白的灰色,1则是表示黑色的

y = np.array([0, 5, 1, 6, 2, 7, 3, 8, 4, 9])

class BPNNet:
    # 初始化必要的几个参数
    def __init__(self, learning_rate=0.3, maxepochs=6e2, convergence_thres=1e-5, hidden_layer=9):
        self.learning_rate = learning_rate  # 学习率
        self.maxepochs = int(maxepochs)     # 最大的
        self.convergence_thres = 1e-5       # 收敛性
        self.hidden_layer = int(hidden_layer)  # 隐藏层

    # 激活函数
    def _sigmoid_activation(self, x, theta):
        x = np.asarray(x)
        theta = np.asarray(theta)
        return 1 / (1 + np.exp(-np.dot(theta.T, x)))
        # 用的1/(1+exp(-x),.T是转置操作,np.exp()函数是求eT的值的函数

    # 计算最终的误差
    def _multiplecost(self, X, y):
    # l1是中间层的输出,l2是输出层的结果
        l1, l2 = self._feedforward(X)
    # 计算误差,这里的l2是前面的h
        inner = y * np.log(l2) + (1 - y) * np.log(1 - l2)
    # 添加符号,将其转换为正值
        return -np.mean(inner)   # 求均值

    # 前向传播函数计算每层的输出结果
    def _feedforward(self, X):
    # l1是中间层的输出
        l1 = self._sigmoid_activation(X.T, self.theta0).T
    # 为中间层添加一个常数列
        l1 = np.column_stack([np.ones(l1.shape[0]), l1])
    # 中间层的输出作为输出层的输入产生结果l2
        l2 = self._sigmoid_activation(l1.T, self.theta1)
        return l1, l2

    # 传入一个结果未知的样本,返回其属于1的概率
    def predict(self, X):
        _, y = self._feedforward(X)
        return y

    # 学习参数,不断迭代至参数收敛,误差最小化
    def learn(self, X, y):
        nobs, ncols = X.shape   # 输出数组的行和列数
        self.theta0 = np.random.normal(0, 0.01, size=(ncols, self.hidden_layer))
        self.theta1 = np.random.normal(0, 0.01, size=(self.hidden_layer + 1, 1))
        self.costs = []
        cost = self._multiplecost(X, y)  # 均值
        self.costs.append(cost)
        costprev = cost + self.convergence_thres + 1
        counter = 0
        # Loop through until convergence
        for counter in range(self.maxepochs):
        # 计算中间层和输出层的输出
            l1, l2 = self._feedforward(X)
        # 首先计算输出层的梯度 然后计算中间层的梯度
            l2_delta = (y - l2) * l2 * (1 - l2)
            l1_delta = l2_delta.T.dot(self.theta1.T) * l1 * (1 - l1)
            # Update parameters
            # theta1是一个5*1的数组,调整完也是
            self.theta1 += l1.T.dot(l2_delta.T) / nobs * self.learning_rate
            self.theta0 += X.T.dot(l1_delta)[:, 1:] / nobs * self.learning_rate
            counter += 1  # Count
            costprev = cost  # Store prev cost
            cost = self._multiplecost(X, y)  # get next cost
            self.costs.append(cost)
            if np.abs(costprev - cost) < self.convergence_thres and counter > 500:
                break


learning_rate = 0.3
maxepochs = 600
convergence_thres = 0.00001
hidden_units = 10

# Train model
models = {}
for i in y:
    model = BPNNet(learning_rate=learning_rate, maxepochs=maxepochs,
                  convergence_thres=convergence_thres, hidden_layer=hidden_units)
    y_train = y == i  # 因为预测列只能是binary classification,所以应把它转化为只有0/1或true/false的形式
    model.learn(X, y_train)
    models[i] = model

# Predict numbers:
testing_probs = pd.DataFrame(columns=y)  # DataFrame是Python中Pandas库中的一种数据结构,它类似excel,是一种二维表。columns是列名
for i in y:
    predictions = models[i].predict(Xtest)[0]
    testing_probs[i] = predictions
pd.set_option('display.max_columns', None)  # 显示所有列
pd.set_option('display.max_rows', None)  # 显示所有行
pd.set_option('display.width', 500)  # 截断问题修改配置,每行展示数据的宽度为500
print('识别结果(概率)\n:', testing_probs)
predicted_numbers = testing_probs.idxmax(axis=1)
print("输入数字集的识别结果为:")
print(list(predicted_numbers))

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
基于BP算法的手写数字识别是一种常见的机器学习任务。下面是一个简单的基于Python的手写数字识别代码示例: ```python import numpy as np # 定义sigmoid函数 def sigmoid(x): return 1 / (1 + np.exp(-x)) # 定义神经网络类 class NeuralNetwork: def __init__(self, input_size, hidden_size, output_size): self.input_size = input_size self.hidden_size = hidden_size self.output_size = output_size # 初始化权重 self.W1 = np.random.randn(self.input_size, self.hidden_size) self.W2 = np.random.randn(self.hidden_size, self.output_size) def forward(self, X): # 前向传播 self.z = np.dot(X, self.W1) self.z2 = sigmoid(self.z) self.z3 = np.dot(self.z2, self.W2) y_hat = sigmoid(self.z3) return y_hat def backward(self, X, y, y_hat, learning_rate): # 反向传播 delta3 = (y_hat - y) * sigmoid(self.z3) * (1 - sigmoid(self.z3)) dW2 = np.dot(self.z2.T, delta3) delta2 = np.dot(delta3, self.W2.T) * sigmoid(self.z2) * (1 - sigmoid(self.z2)) dW1 = np.dot(X.T, delta2) # 更新权重 self.W1 -= learning_rate * dW1 self.W2 -= learning_rate * dW2 def train(self, X, y, epochs, learning_rate): for i in range(epochs): y_hat = self.forward(X) self.backward(X, y, y_hat, learning_rate) def predict(self, X): y_hat = self.forward(X) return np.argmax(y_hat, axis=1) # 示例数据 X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]]) y = np.array([[0], [1], [1], [0]]) # 创建神经网络对象 nn = NeuralNetwork(2, 4, 1) # 训练神经网络 nn.train(X, y, epochs=10000, learning_rate=0.1) # 预测结果 predictions = nn.predict(X) print(predictions) ``` 这段代码实现了一个简单的两层神经网络,使用BP算法进行训练和预测手写数字。其中,`X`是输入数据,`y`是对应的标签。通过调整参数和网络结构,可以提高识别准确率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程日记✧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值