GPU 实例上搭建 Jupyter 深度学习环境

本文将讲解如何让基于腾讯云的GN7系列GPU服务器,完成CIFAR-10图像集的分类模型训练。

0x01 服务器准备

在腾讯云创建购买服务器很简单,等不及的朋友们可以跟着这个视频走一遍就够啦~

https://v.qq.com/x/page/o32055yvqhy.html

GPU 云服务器(GPU Cloud Computing)是基于 GPU 的快速、稳定、弹性的计算服务,主要应用于深度学习训练\推理、图形图像处理以及科学计算等场景。 GPU 云服务器提供和标准 CVM 云服务器一致的方便快捷的管理方式。GPU 云服务器通过其强大的快速处理海量数据的计算性能,有效解放用户的计算压力,提升业务处理效率与竞争力。

这里进入选购页面

GPU 实例上搭建 Jupyter 深度学习环境

推荐选用按量付费实例,创建销毁更加方便,成本控制页更灵活。我们选择合适的附近地域以及有该机型资源的可用区,OS镜像上推荐用最新的CentOS或Ubuntu的稳定版本。云盘挂载这里根据个人需求即可,因为后续也可以再动态挂载CBS云硬盘

记得检查勾选了”免费分配独立公网IP“,因为我们后面是需要远程登录,并通过Web(JupyterUI)访问其服务的。

注意:安全组的选择一定要仔细,建议新建安全组,并放开8888端口,因为这是Jupyter的默认服务端口。

登录方式用对新手更友好一些的密码方法,或者密钥方法都可以,根据习惯即可。

服务器创建完毕后我们可以通过lspci命令,查看并确认GPU型号:

GPU 实例上搭建 Jupyter 深度学习环境

接下来就是驱动安装步骤了~

0x02 CUDA驱动安装

Nvidia官网下载最新的CUDA,包括GPU驱动、SDK和代码Sample等,这里是官方链接

腾讯云GPU服务器GN7机型搭载一整块Nvidia Tesla T4GPU,内置2560个CUDA核心,算力最高可达8.1TFLOPS,显存带宽较前系列也有很大突破,平均实测可以达到200~300GB/s。

目前在主流系统上安装CUDA已经愈发方便了,根据平台参数(如OS、Arch等)一路选择下来即可。这里我们选择deb(local),是相对最方便的方法。最后复制命令,终端执行就OK了。

GPU 实例上搭建 Jupyter 深度学习环境

重启服务器后,可以通过nvdia-smi命令验证CUDA驱动安装成功,并查看设备状态以及驱动版本。CUDA toolkit/SDK默认安装在/usr /local/cuda目录下。

GPU 实例上搭建 Jupyter 深度学习环境

该命令不仅可以看GPU驱动版本,还可以查看实时的进程负载。

0x03 安装PyTorch和Jupyter

PyTorch是目前最主流的开源深度学习框架之一,它包含了一整套地优化的张量库(基于底层的Torch库),并且可以有效地利用系统GPU资源进行模型训练。在图像视觉和自然语言处理等多个AI研究/生产领域有广泛的应用。PyTorch最主要的两个特性是:其Numpy兼容的张量计算可以通过GPU有力地加速;基于其自动微分求导autograd系统可以高效构建深层次的神经网络。

安装依赖软件包

最简单地方法就是通过如下命令,将所需要地依赖包一次性地安装到系统目录下

sudo apt install python3-pip
sudo pip3 install torch torchvision matplotlib jupyterlab jupyter_contrib.nbextensions

或者(可选) 如果你有小洁癖,不想在系统目录安装的话,完全可以通过Python3的venv来创建环境安装依赖,如下:

# 创建并进入工作目录
mkdir workspace && cd workspace
# 创建python virtual env
python3 -m venv .venv
source .venv/bin/activate
# 安装环境到当前目录的.venv下
pip3 install torch torchvision matplotlib jupyterlab jupyter_contrib.nbextensions
# 后续直接启动即可
# jupyter-notebook --no-browser --ip=0.0.0.0

启动Jupyter服务

建议通过tmux会话下启动Jupyter服务,在启动之前(可选)可通过jupyter-notebook password命令设置登录密码。

启动Jupyter,注意需要指定工作目录,注意设定服务监听IP为0.0.0.0.这样才能通过公网IP访问。另外,Jupyter默认的端口号是8888,别忘了在云主机的安全组设置中打开该端口。命令如下:

mkdir workspace
jupyter-notebook --no-browser --ip=0.0.0.0 ./workspace

终端中两次Ctrl+C可以结束Jupyter服务进程。

打开浏览器输入http://服务器地IP:8888,输入登录密码,便能进入Jupyter了。新建一个nootbook验证下,DONE!

GPU 实例上搭建 Jupyter 深度学习环境

一切就绪,那么我们准备开始训练实验吧。

0x04 CIFAR10训练示例

CIFAR-10简介

CIFAR-10(以及CIFAR-100)为8千万个已标注的微小图像的数据集的子集。它由Alex Krizhevsky,Vinod Nair和Geoffrey Hinton收集。CIFAR-10数据集由10个类的60000个32×32彩色图像组成,每个类有6000个图像。有50000个训练图像和10000个测试图像。数据集分为五个训练批次(training batches)和一个测试批次(test batch),每个批次有10000个图像。测试批次包含来自每个类别的恰好1000个随机选择的图像。训练批次以随机顺序包含剩余图像,但一些训练批次可能包含来自一个类别的图像比另一个更多。综合上看,五个训练集之和包含来自每个类的正好5000张图像。

CIFAR-10由于其数据规模相对较小,常作为各大深度学习框架的入门示例。

训练示例脚本

脚本内容与PyTorch官方文档的示例相同,用最简单的两层前馈(feed-forward)卷积神经网络训练一个CIFAR-10图像识别的模型。下面的代码中,我们先下载数据集(打印一些标注数据/图片),然后定义网络结构和SGD优化器,接着进行模型训练,最终输出测试集的性能评估。

当然这一切都在Jupyter的notebook中完成。

import torch
import torchvision
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
​
# download training data
transform = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
​
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2)
testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2)
classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
​
# functions to show an image
def imshow(img):
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()
​
# get some random training images
dataiter = iter(trainloader)
images, labels = dataiter.next()
​
# show images
imshow(torchvision.utils.make_grid(images))
# print labels
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
​
# nn model
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
​
    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x
​
net = Net()
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print('Device: ', device)
net.to(device)
​
# optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
​
# training
print('Start Training')
​
for epoch in range(2):  # loop over the dataset multiple times
    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # get the inputs; data is a list of [inputs, labels]
        inputs, labels = data[0].to(device), data[1].to(device)
        # zero the parameter gradients
        optimizer.zero_grad()
        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        # print statistics
        running_loss += loss.item()
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0
​
print('Finished Training')
​
# result
class_correct = list(0. for i in range(10))
class_total = list(0. for i in range(10))
with torch.no_grad():
    for data in testloader:
        images, labels = data[0].to(device), data[1].to(device)
        outputs = net(images)
        _, predicted = torch.max(outputs, 1)
        c = (predicted == labels).squeeze()
        for i in range(4):
            label = labels[i]
            class_correct[label] += c[i].item()
            class_total[label] += 1
​
for i in range(10):
    print('Accuracy of %5s : %2d %%' % (classes[i], 100 * class_correct[i] / class_total[i]))

几分钟内将输出全部结果,如下图,我们成功地在云服务器中的GPU上训练了我们的模型。

GPU 实例上搭建 Jupyter 深度学习环境

我用本地编辑器PyCharm写代码,该怎么办?

浏览器里的Jupyter Notebook服务确实方便,但也大多情况下用于演示或学习之用。Python项目的开发者们,大部分工作还是会在PyCharm等编辑器下的,因为相比浏览器,本地的编辑器的功能更多更强大。

PyCharm默认支持创建JupyterNotebook文件,但是需要设置下远端的JupyerServer。在项目的设置里,Settings -> Build, Execution, Deployment -> Jupyter -> Jupyter Servers -> Configure Server的配置下,输出Jupyter的Url(形如 http://服务器地IP:8888),并根据提示需要输入Jupyter密码即可。

放心,代码中的绘图(用plt.show()的调用地方)也会在PyCharm的预览中正常显示。

GPU 实例上搭建 Jupyter 深度学习环境

但要注意,由于代码运行是在远端服务器的,代码运行时产生的文件:主要包括运行时下载的数据集文件./data目录、动态保存plot.save()的图片等,它们都会保存在远端目录。如果有需要,可以用本地编辑器(IDE)的SFTP等功能同步数据。

对于VSCode,可以安装 Jupyter的扩展插件,同样的也需要进行相对的远端服务器设置。不过注意VSCode需要本地也有Python解释器,而PyCharm可以设置远程解释器的。

0x05 小结

跟到这里,我们已经完成了在腾讯云GPU云服务器上,安装CUDA驱动、PyTorch以及Jupyter服务,并通过浏览器和PyCharm等环境中创建notebook编写调试Python功能或脚本,最终训练基于CIFAR-10数据集的NN模型。不知道你是否都掌握了呢?

0x06 参考资料

本文来自腾讯云计算社区,转载请注明出处:https://computeinit.com/archives/2669

发表评论

登录后才能评论
交流群