import torchvision.transforms
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
from torchvision import datasets
import numpy as np
import matplotlib.pyplot as plt
# 1.导入mnist数据集
train_dataset = datasets.MNIST(root="./data", train=True, transform=torchvision.transforms.ToTensor(), download=True)
test_dataset = datasets.MNIST(root="./data", train=False, transform=torchvision.transforms.ToTensor(), download=True)
train_data_size = len(train_dataset)
test_data_size = len(test_dataset)
# 2.加载数据集
train_loader = DataLoader(dataset=train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=64, shuffle=True)
# 定义一个学习率
learning_rate = 0.001
epochs = 5
batch_size=1024
# # 测试一下数据集的形状
# for data in test_loader:
# imgs,lables = data
# print(imgs)
# print(imgs.shape)
# print(lables)
# print(lables.shape)
# .对x进行标准化,把输入控制在[0,1]
def Normaliza(x):
# 计算均值
x_mean = np.mean(x)
# 计算标准差
x_std = np.std(x)
# 最后将输入控制在[0,1]之间
X = (x - x_mean) / x_std
return X
# # 定义sigmoid激活函数diff == True 为要求导
# def Sigmoid(x):
# # sigmoid函数
# return 1.0 / (1.0 + np.exp(-x))
# 定义一个softmax来计算y_hat
def softmax(x,w,b):
y_hat = np.dot(x,w) + b
y_exp = np.exp(y_hat)
y_hat = y_exp / np.sum(y_exp, axis=1, keepdims=True)
return y_hat
# # 定义交叉熵损失函数
# def CrossEntropyLoss(y, y_):
# return - np.sum(y * np.log(y_) + (1 - y) * np.log(1 - y_))
# 制作只有0和1的数据
def make_one_hot(data):
return (np.arange(10) == data[:, None]).astype(np.integer)
# def loss(w,x,y,y_hat):
# rows = x.shape[0]
# reg_loss = 0.5 * 1e-3 * np.sum(w * w) # 正则化
#
# cost = -np.sum(y * np.log(y_hat)) / rows
# cost += reg_loss
# return cost
# 定义梯度下降函数进行参数的更新
def grad_desc(x,y,w,b,learning_rate):
# 1.计算y_hat
y_hat = softmax(x,w,b)
# 计算损失函数
rows = x.shape[0] # x.shape[0]为x的行数
# 计算损失值
reg_loss = 0.5 * 1e-3 * np.sum(w * w) # 正则化
cost = -np.sum(y * np.log(y_hat)) / rows
cost += reg_loss
# 更新参数w和b
g_w = np.dot(x.T, (y_hat - y)) / rows
g_w += 1e-3 * w
g_b = np.sum((y_hat - y),axis=0) / rows
# 添加学习率改变梯度下降的速度
w -= g_w * learning_rate
b -= g_b * learning_rate
return w,b,cost
# 初始化w和b
w = np.random.randn(784,10)/np.sqrt(784)
b = np.zeros((1,10)) # 应该是一行十列[[0.],[0.]...[0.]]
loss = 0
writer = SummaryWriter("log")
total_train_step = 0
# 开始训练数据
train_loss = []
test_loss = []
train_acc = []
test_acc = []
for epoch in range(epochs):
print("------第{}轮训练开始------".format(epoch+1))
# 训练数据集上
total_accuracy = 0
total_train_loss = 0
for data in train_loader:
x_train, y_train = data # x_train(64,1,28,28)
X_train = x_train.squeeze().numpy() #X_train(64,28,28),去掉一维的数据,并将Tensor类型转换为ndarray类型
X_train = X_train.reshape(X_train.shape[0],-1)# 调整X_train的形状大小为(64,,28*28)
X_train = Normaliza(X_train) # 对X_train进行归一化数据处理
y_train = y_train.numpy() #(64,)
Y_train = make_one_hot(y_train)
# 使用grad_sec对参数w,b的更新,并计算loss值
w, b, loss = grad_desc(X_train, Y_train, w, b, learning_rate)
# 计算y_pred
y_pred = softmax(X_train,w,b)
y_pred = np.argmax(y_pred,axis=1) #axis = 0按行计算,得到列的性质。axis = 1按列计算,得到行的性质
# 计算准确率
accuracy = (y_pred == y_train).sum()
total_accuracy += accuracy
total_train_loss += loss
train_loss.append(total_train_loss/train_data_size)
train_acc.append(total_accuracy / train_data_size)
# if total_train_step % 100 == 0:
print("训练次数:{},loss:{:.4f},train_accuracy:{:.2f}%".format(total_train_step+1, total_train_loss/train_data_size, 100*total_accuracy / train_data_size))
total_acc_test = 0
total_test_loss = 0
# 测试数据集上
for data in test_loader:
x_test, y_test = data
X_test = x_test.squeeze().numpy()
X_test = X_test.reshape(X_test.shape[0], -1)
X_test = Normaliza(X_test)
y_test = y_test.numpy()
# 计算y_test_pred,并计算正确率
y_test_pred = softmax(X_test,w,b)
# 计算loss
reg_loss = 0.5 * 1e-3 * np.sum(w * w) # 正则化
Y_test = make_one_hot(y_test)
test_cost = -np.sum(Y_test * np.log(y_test_pred)) / X_test.shape[0]
test_cost += reg_loss
y_test_pred = np.argmax(y_test_pred, axis=1)
acc_test = (y_test_pred == y_test).sum()
total_acc_test += acc_test
total_test_loss += test_cost
test_loss.append(total_test_loss/test_data_size)
test_acc.append(total_acc_test/test_data_size)
print("整体测试集上loss:{:.4f},的正确率:{:.2f}%".format(total_test_loss/test_data_size, 100*total_acc_test/test_data_size))
# writer.add_scalars("loss",{"train":total_train_loss/train_data_size,"test":total_test_loss/test_data_size},total_train_step)
# writer.add_scalars("accuracy",{"train_accuracy": 100*total_accuracy / train_data_size, "test_accuracy": 100*total_acc_test/test_data_size}, total_train_step)
total_train_step += 1
x = range(epochs)
ax = plt.gca()
plt.plot(x,train_loss,'b',label="Train_loss")
plt.plot(x,test_loss,'r',label="test_loss")
plt.title("Train and Test loss")
plt.legend(loc='upper left')
plt.figure()
plt.plot(x,train_acc,'b',label="Train_accuracy")
plt.plot(x,test_acc,'r',label="Test_accuracy")
plt.title("Train and Test accuracy")
plt.legend(loc="lower right")
plt.show()
# 定义模型
# class model():
# def __init__(self):
# # 随机化定义Input X的形状
# self.X = np.random.randn(1024, 1)
# self.W = np.random.randn(10, 1024) # 随机化W的值
# self.b = np.random.randn(10, 1) # 随机化b的值
# self.learningrate = 0.01 # 学习率
#
# # 前向传播
# def forward(self, X, y, activate): # activate是激活函数
# self.X = X
# self.z = np.dot(self.W, self.X) + self.b # z=w点乘x+b
# self.y_hat = activate(self.z) # z=sigmoid(z)
# loss = SquareErrorSum(self.y_hat, y) # 通过y,y_hat 计算损失函数
# return loss, self.y_hat # 返回损失值,和预测值y_hat
#
# # 反向传播
# def backward(self, y, activate):
# # 求导
# self.delta = activate(self.z, True) + SquareErrorSum(self.y_hat, y, True)
# # 对W 进行求导
# dW = np.dot(self.delta, self.X.T)
# b = self.delta
# # 更新权重参数 W ,b
# self.W -= self.learningrate * dW
# self.b -= self.learningrate * b
#
# def setLearningrate(self,l):
# self.learningrate = l
#
# model = model()
不调用torch.nn中函数,自己实现cnn的功能进行mnist手写体识别
最新推荐文章于 2023-09-30 10:17:34 发布