手写数字识别+梯度下降法python实现
时间: 2023-08-07 22:02:36 浏览: 159
好的,我可以给你一个简单的手写数字识别和梯度下降法的Python实现,但是需要注意的是,这只是一个示例,实际的手写数字识别模型会更复杂,需要更多的算法和技术。
首先,我们需要准备手写数字数据集。MNIST数据集是一个经典的手写数字数据集,你可以从网上下载到该数据集。
然后,我们需要实现一个简单的神经网络模型。这里我们使用一个3层的全连接神经网络,其中输入层有784个神经元,中间层有128个神经元,输出层有10个神经元,分别对应10个数字。
```python
import numpy as np
class NeuralNetwork:
def __init__(self, input_size, hidden_size, output_size):
self.weights1 = np.random.normal(scale=0.1, size=(input_size, hidden_size))
self.weights2 = np.random.normal(scale=0.1, size=(hidden_size, output_size))
def forward(self, x):
hidden = np.dot(x, self.weights1)
hidden = np.maximum(0, hidden) # ReLU activation
output = np.dot(hidden, self.weights2)
return output
def predict(self, x):
return np.argmax(self.forward(x), axis=1)
```
接下来,我们需要实现梯度下降法来训练我们的神经网络模型。这里我们使用交叉熵损失函数和反向传播算法来计算梯度。
```python
def softmax(x):
exps = np.exp(x - np.max(x, axis=1, keepdims=True))
return exps / np.sum(exps, axis=1, keepdims=True)
def cross_entropy_loss(y_pred, y_true):
m = y_true.shape[0]
p = softmax(y_pred)
log_likelihood = -np.log(p[range(m), y_true])
loss = np.sum(log_likelihood) / m
return loss
def backpropagation(x, y_true, y_pred, hidden, nn, learning_rate):
m = y_true.shape[0]
grad_y_pred = softmax(y_pred)
grad_y_pred[range(m), y_true] -= 1
grad_y_pred /= m
grad_weights2 = np.dot(hidden.T, grad_y_pred)
grad_hidden = np.dot(grad_y_pred, nn.weights2.T)
grad_hidden[hidden <= 0] = 0
grad_weights1 = np.dot(x.T, grad_hidden)
nn.weights1 -= learning_rate * grad_weights1
nn.weights2 -= learning_rate * grad_weights2
def train(x_train, y_train, nn, learning_rate, num_epochs):
for epoch in range(num_epochs):
y_pred = nn.forward(x_train)
loss = cross_entropy_loss(y_pred, y_train)
if epoch % 10 == 0:
print(f"Epoch {epoch}, Loss: {loss:.3f}")
hidden = np.dot(x_train, nn.weights1)
hidden = np.maximum(0, hidden)
backpropagation(x_train, y_train, y_pred, hidden, nn, learning_rate)
```
最后,我们可以用训练好的模型来预测手写数字的标签。
```python
import gzip
import pickle
# Load data
with gzip.open("mnist.pkl.gz", "rb") as f:
train_data, _, test_data = pickle.load(f, encoding="latin1")
x_train, y_train = train_data
# Normalize data
mean = np.mean(x_train)
std = np.std(x_train)
x_train = (x_train - mean) / std
# Train model
nn = NeuralNetwork(784, 128, 10)
train(x_train, y_train, nn, learning_rate=0.1, num_epochs=1000)
# Predict test data
x_test, y_test = test_data
x_test = (x_test - mean) / std
y_pred = nn.predict(x_test)
accuracy = np.mean(y_pred == y_test)
print(f"Test Accuracy: {accuracy:.3f}")
```
这样,我们就可以用梯度下降法训练一个简单的神经网络模型来识别手写数字了。
阅读全文