手写代码利用numpy实现mnist手写数字识别
时间: 2023-11-12 16:04:21 浏览: 105
好的,下面是利用Numpy实现MNIST手写数字识别的代码示例:
```python
import numpy as np
import gzip
# 加载MNIST数据集
def load_data():
with gzip.open('train-images-idx3-ubyte.gz', 'rb') as f:
train_data = np.frombuffer(f.read(), np.uint8, offset=16).reshape(-1, 28 * 28)
with gzip.open('train-labels-idx1-ubyte.gz', 'rb') as f:
train_label = np.frombuffer(f.read(), np.uint8, offset=8)
with gzip.open('t10k-images-idx3-ubyte.gz', 'rb') as f:
test_data = np.frombuffer(f.read(), np.uint8, offset=16).reshape(-1, 28 * 28)
with gzip.open('t10k-labels-idx1-ubyte.gz', 'rb') as f:
test_label = np.frombuffer(f.read(), np.uint8, offset=8)
return train_data, train_label, test_data, test_label
# 将标签转换为one-hot向量
def to_one_hot(labels, num_classes):
num_labels = labels.shape[0]
one_hot = np.zeros((num_labels, num_classes))
one_hot[np.arange(num_labels), labels] = 1
return one_hot
# Softmax函数
def softmax(x):
exp_x = np.exp(x)
return exp_x / np.sum(exp_x, axis=1, keepdims=True)
# 损失函数
def cross_entropy_loss(y_pred, y_true):
num_samples = y_pred.shape[0]
loss = -np.sum(y_true * np.log(y_pred)) / num_samples
return loss
# 定义模型
class Model:
def __init__(self, input_dim, hidden_dim, output_dim):
self.input_dim = input_dim
self.hidden_dim = hidden_dim
self.output_dim = output_dim
self.W1 = np.random.randn(input_dim, hidden_dim)
self.b1 = np.zeros((1, hidden_dim))
self.W2 = np.random.randn(hidden_dim, output_dim)
self.b2 = np.zeros((1, output_dim))
# 前向传播
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
self.a2 = softmax(self.z2)
return self.a2
# 反向传播
def backward(self, x, y_true, y_pred):
delta2 = y_pred - y_true
delta1 = np.dot(delta2, self.W2.T) * (1 - np.power(self.a1, 2))
dW2 = np.dot(self.a1.T, delta2)
db2 = np.sum(delta2, axis=0, keepdims=True)
dW1 = np.dot(x.T, delta1)
db1 = np.sum(delta1, axis=0)
return dW1, db1, dW2, db2
# 训练模型
def train(self, x_train, y_train, epochs, learning_rate):
num_samples, input_dim = x_train.shape
num_classes = y_train.shape[1]
for epoch in range(epochs):
for i in range(num_samples):
x = x_train[i:i+1]
y_true = y_train[i:i+1]
y_pred = self.forward(x)
dW1, db1, dW2, db2 = self.backward(x, y_true, y_pred)
self.W1 -= learning_rate * dW1
self.b1 -= learning_rate * db1
self.W2 -= learning_rate * dW2
self.b2 -= learning_rate * db2
y_pred_train = self.forward(x_train)
train_loss = cross_entropy_loss(y_pred_train, y_train)
print('Epoch %d, loss: %f' % (epoch, train_loss))
# 测试模型
def test(self, x_test, y_test):
y_pred = self.forward(x_test)
test_loss = cross_entropy_loss(y_pred, y_test)
accuracy = np.mean(np.argmax(y_pred, axis=1) == np.argmax(y_test, axis=1))
print('Test loss: %f, accuracy: %f' % (test_loss, accuracy))
# 加载数据集
x_train, y_train, x_test, y_test = load_data()
# 将标签转换为one-hot向量
y_train = to_one_hot(y_train, 10)
y_test = to_one_hot(y_test, 10)
# 定义模型
model = Model(input_dim=784, hidden_dim=128, output_dim=10)
# 训练模型
model.train(x_train, y_train, epochs=10, learning_rate=0.01)
# 测试模型
model.test(x_test, y_test)
```
这段代码实现了一个单隐藏层的神经网络,用于对MNIST手写数字进行分类。其中,softmax函数用于将神经网络的输出转换为概率分布,cross_entropy_loss函数用于计算损失函数,Model类定义了神经网络的结构和训练过程。在训练过程中,我们通过反向传播算法更新权重和偏置,将模型训练到收敛。最后,我们通过测试集评估模型的性能。
阅读全文