numpy实现手写体识别,网络结构不要过于复杂,输出包括权值,参数
时间: 2024-01-26 08:02:33 浏览: 21
好的,手写体识别是一个经典的图像分类任务,我们可以使用numpy实现一个简单的全连接神经网络来完成该任务。
首先,我们需要加载手写数字数据集,可以使用sklearn库中的load_digits函数:
```python
from sklearn.datasets import load_digits
digits = load_digits()
X = digits.data
y = digits.target
```
接下来,我们需要对数据进行预处理,将像素值归一化到0到1之间,并将标签进行one-hot编码:
```python
import numpy as np
# 归一化
X = X / 16.0
# 将标签进行one-hot编码
num_classes = 10
y_onehot = np.eye(num_classes)[y]
```
然后,我们可以定义一个简单的全连接神经网络,包括一个输入层、一个隐藏层和一个输出层:
```python
class NeuralNetwork:
def __init__(self, input_size, hidden_size, output_size):
self.W1 = np.random.randn(input_size, hidden_size) / np.sqrt(input_size)
self.b1 = np.zeros(hidden_size)
self.W2 = np.random.randn(hidden_size, output_size) / np.sqrt(hidden_size)
self.b2 = np.zeros(output_size)
def forward(self, X):
self.z1 = np.dot(X, self.W1) + self.b1
self.a1 = np.tanh(self.z1)
self.z2 = np.dot(self.a1, self.W2) + self.b2
exp_scores = np.exp(self.z2)
return exp_scores / np.sum(exp_scores, axis=1, keepdims=True)
def loss(self, X, y):
num_examples = X.shape[0]
probs = self.forward(X)
corect_logprobs = -np.log(probs[range(num_examples), y])
data_loss = np.sum(corect_logprobs)
return 1./num_examples * data_loss
def predict(self, X):
probs = self.forward(X)
return np.argmax(probs, axis=1)
```
其中,forward函数实现了前向传播,loss函数计算损失,predict函数用于预测类别。
最后,我们可以训练该神经网络,使用随机梯度下降算法进行优化:
```python
input_size = X.shape[1]
hidden_size = 25
output_size = num_classes
nn = NeuralNetwork(input_size, hidden_size, output_size)
learning_rate = 0.1
num_iterations = 10000
for i in range(num_iterations):
# 随机选择一个样本
idx = np.random.randint(X.shape[0])
x_i = X[[idx], :]
y_i = y_onehot[[idx], :]
# 前向传播和反向传播
probs = nn.forward(x_i)
delta3 = probs
delta3[range(1), y_i] -= 1
dW2 = np.dot(nn.a1.T, delta3)
db2 = np.sum(delta3, axis=0)
delta2 = np.dot(delta3, nn.W2.T) * (1 - np.power(nn.a1, 2))
dW1 = np.dot(x_i.T, delta2)
db1 = np.sum(delta2, axis=0)
# 更新参数
nn.W1 -= learning_rate * dW1
nn.b1 -= learning_rate * db1
nn.W2 -= learning_rate * dW2
nn.b2 -= learning_rate * db2
# 每1000次迭代输出一次损失
if i % 1000 == 0:
print("Iteration {}: loss = {}".format(i, nn.loss(X, y)))
```
训练完成后,我们可以使用predict函数对新的手写数字进行分类预测,最后输出权值和参数:
```python
# 预测类别
y_pred = nn.predict(X)
# 输出权值和参数
print("W1 = {}".format(nn.W1))
print("b1 = {}".format(nn.b1))
print("W2 = {}".format(nn.W2))
print("b2 = {}".format(nn.b2))
```