一、Kaggle介绍
Kaggle是在AI行业领域内,一个国内外都比较出名的网站,国内的阿里天池就是对标这个网站。上面有着丰富的数据集,包括计算机视觉CV领域的(包括:图像识别、目标检测、语义分割等)数据集,也有像波士顿房价预测这样的数据集,还有语音识别方面的数据集等等,上面不定时会举办一些比赛,任何注册成员都可以参加,Kaggle不但免费提供数据集,每周还有一定的免费GPU和TPU使用额度(GPU每周免费使用30个小时,TPU免费使用20个小时),我们的代码可以在kaggle所提供的NoteBook上运行,你可以学习参考别人分享的代码,也可以将自己的代码分享出来。总的来说,这是一个AI方面学习者很好的社区,有着良好的开源氛围,通过参加比赛和交流也可以增加我们的相关经验,免费的GPU和CPU也降低了我们学习的门槛。
Kaggle网站地址:Kaggle: Your Machine Learning and Data Science Community
二、Digit Recognizer竞赛
这是一个计算机视觉图像识别方面入门级的比赛,你可以理解为学习计算机视觉方面的“Hello World”,这个Mnist手写数字数据集可以追溯到上个世纪,可能比你的年纪还要大,当时是训练后运用到 邮票编码的数字识别 和 银行支票的数字识别,有些模型甚至到现在都还在使用。
数据集简介:
MNIST数据集由Yann LeCun搜集,是一个大型的手写体数字数据库,通常用于训练各种图像处理系统,也被广泛用于机器学习领域的训练和测试。MNIST数字文字识别数据集数据量不会太多,而且是单色的图像,较简单,适合深度学习初学者练习建立模型、训练、预测。MNIST数据库中的图像集是NIST(National Institute of Standards and Technology)的两个数据库的组合:专用数据库1和特殊数据库3。数据集是有250人手写数字组成,一半是高中生,一半是美国人口普查局。
MNIST数据集共有训练数据60000项、测试数据10000项。每张图像的大小为28*28(像素),每张图像都为灰度图像,位深度为8(灰度图像是0-255)。大概长这样:
三、实战代码
我的代码是在Kaggle的Notebook上直接运行的。
1.训练:
import os
import math
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
import torch
from torch.utils.data import DataLoader, Dataset
import matplotlib.pyplot as plt
import torch.nn as nn
from torch.autograd import Variable
from torch.nn import functional as F
from torchvision import datasets, models, transforms
import torch.optim as optim
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
dataframe_train_valid = pd.read_csv(os.path.join('../input/digit-recognizer/', 'train.csv'), dtype=np.float32)
dataframe_test = pd.read_csv(os.path.join('../input/digit-recognizer/', 'test.csv'), dtype=np.float32)
class mnist_data(Dataset):
def __init__(self, type, dataframe, transform):
if type == 'train' or type == 'valid':
labels = dataframe.label.values
features = (dataframe.loc[:, dataframe.columns != "label"].values)
# 划分训练集与验证集
features_train, features_valid, labels_train, labels_valid = \
train_test_split(features, labels, test_size=0.2, random_state=0)
if type == 'train':
self.X = features_train.reshape((-1,28,28))
self.y = labels_train
elif type == 'valid':
self.X = features_valid.reshape((-1,28,28))
self.y = labels_valid
if type == 'test':
self.X = dataframe.values.reshape((-1,28,28))
self.y = None
self.transform = transform
def __getitem__(self, index):
if self.y is not None:
return self.y[index], self.transform(self.X[index])
else:
return self.transform(self.X[index])
def __len__(self):
return self.X.shape[0]
batch_size = 256
train_dataset = mnist_data('train', dataframe_train_valid,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=(0.1307,), std=(0.3081,))
]))
valid_dataset = mnist_data('valid', dataframe_train_valid,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=(0.1307,), std=(0.3081,))
]))
test_dataset = mnist_data('test', dataframe_test,
transform=transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=(0.1307,), std=(0.3081,))
]))
train_dataloader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=False)
valid_dataloader = DataLoader(dataset=valid_dataset, batch_size=batch_size, shuffle=False)
test_dataloader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)
model = models.resnet18()#pretrained=True
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 10)
model.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)
# 选择优化器
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)
#optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9, weight_decay=1e-2)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer=optimizer, T_max=1000)#, eta_min=1e-6
'''
# 若训练时测量值(如loss)停滞,则调整学习率
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer,
patience=5,
verbose=1,
factor=0.5,
min_lr=1e-5)'''
# 选择loss function
criterion = nn.CrossEntropyLoss()
# 使用gpu进行训练
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
model.to(device)
criterion.to(device)
count = 0
loss_list = []
iteration_list = []
accuracy_list = []
best_accuracy = 0
for epoch in range(1000):
for i, (labels, images) in enumerate(train_dataloader):
train = Variable(images.type(torch.FloatTensor)).to(device)
labels = Variable(labels.type(torch.LongTensor)).to(device)
optimizer.zero_grad()
outputs = model(train)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
count = count + 1
if count % 50 == 0:
# 检查loss与该模型在验证集下的识别准确率
correct = 0
total = 0
for i, (labels, images) in enumerate(valid_dataloader):
valid = Variable(images.type(torch.FloatTensor)).to(device)
labels = Variable(labels.type(torch.LongTensor)).to(device)
outputs = model(valid)
predicted = torch.max(outputs.data, 1)[1]
total += len(labels)
correct += (predicted == labels).sum()
accuracy = 100 * correct / float(total)
loss_list.append(loss.data)
iteration_list.append(count)
accuracy_list.append(accuracy)
print('Epoch:{} Iteration: {} Loss: {} Accuracy: {} %'.format(epoch,count,
loss.data,
accuracy))
if accuracy > best_accuracy:
torch.save(model.state_dict(),'./mymodel.pt')
scheduler.step()#loss
optimizer.step()
2.模型评估并且生成提交文件:
from torchvision import datasets, models, transforms
import torch.nn as nn
model = models.resnet18()#pretrained=True
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 10)#识别种类数
model.conv1 = nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3, bias=False)
model.load_state_dict(torch.load('./mymodel.pt'))
model.eval()
model.to(device)
prediction = []
with torch.no_grad():
for i, images in enumerate(test_dataloader):
test = Variable(images.type(torch.FloatTensor)).to(device)
outputs = model(test)
predicted = torch.max(outputs.data, 1)[1]
prediction.append(predicted.cpu())
p = [x.numpy() for x in prediction]
p = np.array(p,dtype=object)
p = np.hstack(p)
print(p.shape)
submission = pd.DataFrame({
"ImageId": np.arange(len(p))+1,
"Label": p.tolist()
})
submission.to_csv('./sample_submission_leonard2021.csv', index=False)
print(submission)
?完成训练和评估后,可以刷新Output界面,将 提交文件 下载到你的电脑再上传到比赛界面中就可得到你的成绩和排名了。
我使用的自己改造过ResNet18的网络,将网络的输入图片格式改为单通道,并且将全连接层的输出改为10,使用的是Aadm优化器(初始学习率为0.01),学习率调整算法为CosineAnnealingLR余弦退火。
我简单训练提交后,比赛的评估成绩是准确率为0.99325,排名在前17%左右,中规中矩,你也可以自己改进模型和调参,或者尝试冻结部分网络参数,来达到更好的成绩。
?——————————————————————————————————————————
如果本文对你有帮助,欢迎一键三连!!!
|