深度学习之初识篇——小白也能跑通的深度学习万能框架【交通标识牌检测】

news/2024/10/23 9:34:58/

目录

      • 环境下载;点击即可
      • 数据集下载;点击即可
      • 深度学习环境配置
        • 点击下载深度学习环境
        • 数据集准备
        • 使用自己标注的数据集
        • 使用标注软件
        • 数据准备
        • VOC标签格式转yolo格式并划分训练集和测试集
      • 部署和训练深度学习项目
        • 克隆项目
        • 获得预训练权重
        • 训练自己的模型
      • 训练参数详解
      • 启用tensorbord查看参数
      • 输出参数详解
      • 每文一语

本文是作为后续跑深度学习的一个案例教程,可以作为快速搭建自己的深度学习框架,预计按照本教程3~5分钟即可完成,这是因为深度学习是一个框架学习,不像机器学习那样,我们需要进行部署自己的项目代码,做一些较为复杂的算法处理和学习,而深度学习却可以。

深度学习就像人的大脑一样,世界上有很多个人,不同的大脑会有不同的想法,就像牛顿对待熟透落地的苹果一样,诗人面对晚霞下的那一句“落霞与孤鹜齐飞,秋水共长天一色”的宁静致远。

这是就是为什么人有人说他难,也有人它晦涩难懂。

下面我们开始实战项目演练

环境下载;点击即可

数据集下载;点击即可

有需要全套的项目工程;包含训练参数集最佳权重,私信即可

深度学习环境配置

众所周知,深度学习配置环境就是一个比较头疼的事情,本次教程由于是快速部署,默认你是有深度学习环境(pytorch)的,如果没有的话,可以点击下面的链接进行下载,我已经部署好了GPU版本的pytorch的深度学习环境,解压可以使用。

点击下载深度学习环境

解压之后,放在我们的anaconda安装好的目录下;如果你是按照默认路径,如下所示:

在这里插入图片描述

然后利用打开我们的anaconda;激活环境;

在这里插入图片描述

打开我们的pycharm,按照如下操作进行,将本地的Python工程项目进行和我们刚刚新激活的环境链接起来:

在这里插入图片描述在这里插入图片描述

数据集准备

使用自己标注的数据集

由于目前深度学习生态在国内比较的好,应用也比较的广泛,例如在:医疗、农业、交通等领域;当然我们可以使用自己的标注的数据集,也就是说从原始的数据集开始自己标注一张一张的,这样的好处是什么呢?我们可以应用到自己的领域,有些时候网上并不能找到一些标注好的数据集,比如在医学方面,有些疾病的医疗影像是不会公开的,是需要自己进行因地制宜,完成数据的标注的。

使用标注软件

这里主要讲的是在window系统中的安装,首先打开cmd命令行(快捷键:win+R)。进入cmd命令行控制台。输入如下的命令

pip install labelimg -i https://pypi.tuna.tsinghua.edu.cn/simple

运行如上命令后,系统就会自动下载labelimg相关的依赖。由于这是一个很轻量的工具,所以下载起来很快,当出现如下红色框框中的告诉我们成功安装的时候,说明labelimg安装成功了。

数据准备

首先这里需要准备我们需要打标注的数据集。这里我建议新建一个名为VOC2007的文件夹,里面创建一个名为JPEGImages的文件夹存放我们需要打标签的图片文件;再创建一个名为Annotations存放标注的标签文件;最后创建一个名为 predefined_classes.txt 的txt文件来存放所要标注的类别名称。

VOC2007的目录结构为:

├── VOC2007
│├── JPEGImages 存放需要打标签的图片文件
│├── Annotations 存放标注的标签文件
│├── predefined_classes.txt 定义自己要标注的所有类别(这个文件可有可无,但是在我们定义类别比较多的时候,最好有这个创建一个这样的txt文件来存放类别)

在这里插入图片描述
在这里插入图片描述

打开cmd命令终端(快捷键:win+R)。进入到刚刚创建的这个VOC2007路径(这个很重要,涉及到能不能利用predefined_classes.txt 这个txt文件中定义的类别,我在这里卡了很久,一度以为不能显示txt文件中定义的类别是我安装有问题)。

执行如图中的命令进入到VOC2007路径下(每个人的路径都不一样,按个人的路径去写)如下图所示:可以看到进入到相应的目录了。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

上面具体参数我就不说明了,后期会有专门的教程进行解释

通过大量的标注之后,我们会产生大量的标注文件,这里我们使用的是xml格式的,因为比较显著,看起来具有可读性,但是我们yolov5支持的是txt格式的,相信细心的小伙伴已经发现了,所以我们是通常自己标注为xml文件之后,使用脚本批量进行转换

VOC标签格式转yolo格式并划分训练集和测试集

这里就需要对xml格式的标签文件转换为txt文件。同时训练自己的yolov5检测模型的时候,数据集需要划分为训练集和验证集。这里提供了一份代码将xml格式的标注文件转换为txt格式的标注文件,并按比例划分为训练集和验证集。先上代码再讲解代码的注意事项。

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import random
from shutil import copyfileclasses = ["标签1", "标签2"]#根据自己标注的进行填写TRAIN_RATIO = 80#训练集比例def clear_hidden_files(path):dir_list = os.listdir(path)for i in dir_list:abspath = os.path.join(os.path.abspath(path), i)if os.path.isfile(abspath):if i.startswith("._"):os.remove(abspath)else:clear_hidden_files(abspath)def convert(size, box):dw = 1./size[0]dh = 1./size[1]x = (box[0] + box[1])/2.0y = (box[2] + box[3])/2.0w = box[1] - box[0]h = box[3] - box[2]x = x*dww = w*dwy = y*dhh = h*dhreturn (x,y,w,h)def convert_annotation(image_id):in_file = open('VOCdevkit/VOC2007/Annotations/%s.xml' %image_id)#输入的文件路径out_file = open('VOCdevkit/VOC2007/YOLOLabels/%s.txt' %image_id, 'w')#输出文件路径tree=ET.parse(in_file)root = tree.getroot()size = root.find('size')w = int(size.find('width').text)h = int(size.find('height').text)for obj in root.iter('object'):difficult = obj.find('difficult').textcls = obj.find('name').textif cls not in classes or int(difficult) == 1:continuecls_id = classes.index(cls)xmlbox = obj.find('bndbox')b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))bb = convert((w,h), b)out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')in_file.close()out_file.close()wd = os.getcwd()
wd = os.getcwd()
data_base_dir = os.path.join(wd, "VOCdevkit/")
if not os.path.isdir(data_base_dir):os.mkdir(data_base_dir)
work_sapce_dir = os.path.join(data_base_dir, "VOC2007/")
if not os.path.isdir(work_sapce_dir):os.mkdir(work_sapce_dir)
annotation_dir = os.path.join(work_sapce_dir, "Annotations/")
if not os.path.isdir(annotation_dir):os.mkdir(annotation_dir)
clear_hidden_files(annotation_dir)
image_dir = os.path.join(work_sapce_dir, "JPEGImages/")
if not os.path.isdir(image_dir):os.mkdir(image_dir)
clear_hidden_files(image_dir)
yolo_labels_dir = os.path.join(work_sapce_dir, "YOLOLabels/")
if not os.path.isdir(yolo_labels_dir):os.mkdir(yolo_labels_dir)
clear_hidden_files(yolo_labels_dir)
yolov5_images_dir = os.path.join(data_base_dir, "images/")
if not os.path.isdir(yolov5_images_dir):os.mkdir(yolov5_images_dir)
clear_hidden_files(yolov5_images_dir)
yolov5_labels_dir = os.path.join(data_base_dir, "labels/")
if not os.path.isdir(yolov5_labels_dir):os.mkdir(yolov5_labels_dir)
clear_hidden_files(yolov5_labels_dir)
yolov5_images_train_dir = os.path.join(yolov5_images_dir, "train/")
if not os.path.isdir(yolov5_images_train_dir):os.mkdir(yolov5_images_train_dir)
clear_hidden_files(yolov5_images_train_dir)
yolov5_images_test_dir = os.path.join(yolov5_images_dir, "val/")
if not os.path.isdir(yolov5_images_test_dir):os.mkdir(yolov5_images_test_dir)
clear_hidden_files(yolov5_images_test_dir)
yolov5_labels_train_dir = os.path.join(yolov5_labels_dir, "train/")
if not os.path.isdir(yolov5_labels_train_dir):os.mkdir(yolov5_labels_train_dir)
clear_hidden_files(yolov5_labels_train_dir)
yolov5_labels_test_dir = os.path.join(yolov5_labels_dir, "val/")
if not os.path.isdir(yolov5_labels_test_dir):os.mkdir(yolov5_labels_test_dir)
clear_hidden_files(yolov5_labels_test_dir)train_file = open(os.path.join(wd, "yolov5_train.txt"), 'w')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'w')
train_file.close()
test_file.close()
train_file = open(os.path.join(wd, "yolov5_train.txt"), 'a')
test_file = open(os.path.join(wd, "yolov5_val.txt"), 'a')
list_imgs = os.listdir(image_dir) # list image files
prob = random.randint(1, 100)
print("Probability: %d" % prob)
for i in range(0,len(list_imgs)):path = os.path.join(image_dir,list_imgs[i])if os.path.isfile(path):image_path = image_dir + list_imgs[i]voc_path = list_imgs[i](nameWithoutExtention, extention) = os.path.splitext(os.path.basename(image_path))(voc_nameWithoutExtention, voc_extention) = os.path.splitext(os.path.basename(voc_path))annotation_name = nameWithoutExtention + '.xml'annotation_path = os.path.join(annotation_dir, annotation_name)label_name = nameWithoutExtention + '.txt'label_path = os.path.join(yolo_labels_dir, label_name)prob = random.randint(1, 100)print("Probability: %d" % prob)if(prob < TRAIN_RATIO): # train datasetif os.path.exists(annotation_path):train_file.write(image_path + '\n')convert_annotation(nameWithoutExtention) # convert labelcopyfile(image_path, yolov5_images_train_dir + voc_path)copyfile(label_path, yolov5_labels_train_dir + label_name)else: # test datasetif os.path.exists(annotation_path):test_file.write(image_path + '\n')convert_annotation(nameWithoutExtention) # convert labelcopyfile(image_path, yolov5_images_test_dir + voc_path)copyfile(label_path, yolov5_labels_test_dir + label_name)
train_file.close()
test_file.close()

只需要改动上述加了注释的几个地方

最后展示:

在这里插入图片描述
在这里插入图片描述

可能上述的东西你可以直接通过其他途径获得,但是下面的东西就需要注意了,是重点!

部署和训练深度学习项目

克隆项目

YOLOv5的代码是开源的,因此我们可以从github上克隆其源码。不得不说GitHub的确是全球最大的男性交友网站,里面的人个个都是人才,yolov5发布才一年左右的时间,YOLOv5就已经更新了5个分支了,分别是yolov5.1-yolov5.5分支。该项目就是利用的yolov5.5分支来作为讲解。

首先打开yolov5的github的官网(这个网站在国外打开是很慢的,而且是有的时候能正常打开,有的时候是进不去的,但是大家第一次打不开的话,一定要多打开几次。)打开的官网界面如下,这个就是大神glenn-jocher开源的yolov5的项目。

在这里插入图片描述
在这里插入图片描述

现在来对代码的整体目录做一个介绍:

├── data:主要是存放一些超参数的配置文件(这些文件(yaml文件)是用来配置训练集和测试集还有验证集的路径的,其中还包括目标检测的种类数和种类的名称);还有一些官方提供测试的图片。如果是训练自己的数据集的话,那么就需要修改其中的yaml文件。但是自己的数据集不建议放在这个路径下面,而是建议把数据集放到yolov5项目的同级目录下面。

├── models:里面主要是一些网络构建的配置文件和函数,其中包含了该项目的四个不同的版本,分别为是s、m、l、x。从名字就可以看出,这几个版本的大小。他们的检测测度分别都是从快到慢,但是精确度分别是从低到高。这就是所谓的鱼和熊掌不可兼得。如果训练自己的数据集的话,就需要修改这里面相对应的yaml文件来训练自己模型。

├── utils:存放的是工具类的函数,里面有loss函数,metrics函数,plots函数等等。

├── weights:放置训练好的权重参数。

├── detect.py:利用训练好的权重参数进行目标检测,可以进行图像、视频和摄像头的检测。

├── train.py:训练自己的数据集的函数。

├── test.py:测试训练的结果的函数。

├──requirements.txt:这是一个文本文件,里面写着使用yolov5项目的环境依赖包的一些版本,可以利用该文本导入相应版本的包。

以上就是yolov5项目代码的整体介绍。我们训练和测试自己的数据集基本就是利用到如上的代码。

数据最好放在最外一级目录中,然后数据集的目录格式如下图所示。大家一定要严格按我的格式来,否则非常容易出问题。

打开requirements.txt这个文件,可以看到里面有很多的依赖库和其对应的版本要求。我们打开pycharm的命令终端,在中输入如下的命令,就可以安装了。

pip install -r requirements.txt

如果你之前使用的是我的环境,那么此处就不需要安装了,我的里面已经安装好了

获得预训练权重

一般为了缩短网络的训练时间,并达到更好的精度,我们一般加载预训练权重进行网络的训练。而yolov5的5.0版本给我们提供了几个预训练权重,我们可以对应我们不同的需求选择不同的版本的预训练权重。通过如下的图可以获得权重的名字和大小信息,可以预料的到,预训练权重越大,训练出来的精度就会相对来说越高,但是其检测的速度就会越慢。预训练权重可以通过这个网址进行下载,本次训练自己的数据集用的预训练权重为yolov5s.pt。

在这里插入图片描述

训练自己的模型

预训练模型和数据集都准备好了,就可以开始训练自己的yolov5目标检测模型了,训练目标检测模型需要修改两个yaml文件中的参数。一个是data目录下的相应的yaml文件,一个是model目录文件下的相应的yaml文件。

修改data目录下的相应的yaml文件。找到目录下的voc.yaml文件,将该文件复制一份,将复制的文件重命名,最好和项目相关,这样方便后面操作。

在这里插入图片描述

打开这个文件夹修改其中的参数,首先将箭头1中的那一行代码注释掉(我已经注释掉了),如果不注释这行代码训练的时候会报错;箭头2中需要将训练和测试的数据集的路径填上(最好要填绝对路径,有时候由目录结构的问题会莫名奇妙的报错);箭头3中需要检测的类别数,我这里是识别交通标志物,所以这里填写45;最后箭头4中填写需要识别的类别的名字(必须是英文或者自定义ID,否则会乱码识别不出来)。到这里和data目录下的yaml文件就修改好了。

在这里插入图片描述

修改模型配置文件

在这里插入图片描述

至此,相应的配置参数就修改好了。

如果上面的数据集和两个yaml文件的参数都修改好了的话,就可以开始yolov5的训练了。首先我们找到train.py这个py文件。

在这里插入图片描述

然后找到主函数的入口,这里面有模型的主要参数。模型的主要参数解析如下所示。

if __name__ == '__main__':
"""opt模型主要参数解析:--weights:初始化的权重文件的路径地址--cfg:模型yaml文件的路径地址--data:数据yaml文件的路径地址--hyp:超参数文件路径地址--epochs:训练轮次--batch-size:喂入批次文件的多少--img-size:输入图片尺寸--rect:是否采用矩形训练,默认False--resume:接着打断训练上次的结果接着训练--nosave:不保存模型,默认False--notest:不进行test,默认False--noautoanchor:不自动调整anchor,默认False--evolve:是否进行超参数进化,默认False--bucket:谷歌云盘bucket,一般不会用到--cache-images:是否提前缓存图片到内存,以加快训练速度,默认False--image-weights:使用加权图像选择进行训练--device:训练的设备,cpu;0(表示一个gpu设备cuda:0);0,1,2,3(多个gpu设备)--multi-scale:是否进行多尺度训练,默认False--single-cls:数据集是否只有一个类别,默认False--adam:是否使用adam优化器--sync-bn:是否使用跨卡同步BN,在DDP模式使用--local_rank:DDP参数,请勿修改--workers:最大工作核心数--project:训练模型的保存位置--name:模型保存的目录名称--exist-ok:模型目录是否存在,不存在就创建
"""parser = argparse.ArgumentParser()parser.add_argument('--weights', type=str, default='yolov5s.pt', help='initial weights path')parser.add_argument('--cfg', type=str, default='', help='model.yaml path')parser.add_argument('--data', type=str, default='data/coco128.yaml', help='data.yaml path')parser.add_argument('--hyp', type=str, default='data/hyp.scratch.yaml', help='hyperparameters path')parser.add_argument('--epochs', type=int, default=300)parser.add_argument('--batch-size', type=int, default=16, help='total batch size for all GPUs')parser.add_argument('--img-size', nargs='+', type=int, default=[640, 640], help='[train, test] image sizes')parser.add_argument('--rect', action='store_true', help='rectangular training')parser.add_argument('--resume', nargs='?', const=True, default=False, help='resume most recent training')parser.add_argument('--nosave', action='store_true', help='only save final checkpoint')parser.add_argument('--notest', action='store_true', help='only test final epoch')parser.add_argument('--noautoanchor', action='store_true', help='disable autoanchor check')parser.add_argument('--evolve', action='store_true', help='evolve hyperparameters')parser.add_argument('--bucket', type=str, default='', help='gsutil bucket')parser.add_argument('--cache-images', action='store_true', help='cache images for faster training')parser.add_argument('--image-weights', action='store_true', help='use weighted image selection for training')parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')parser.add_argument('--multi-scale', action='store_true', help='vary img-size +/- 50%%')parser.add_argument('--single-cls', action='store_true', help='train multi-class data as single-class')parser.add_argument('--adam', action='store_true', help='use torch.optim.Adam() optimizer')parser.add_argument('--sync-bn', action='store_true', help='use SyncBatchNorm, only available in DDP mode')parser.add_argument('--local_rank', type=int, default=-1, help='DDP parameter, do not modify')parser.add_argument('--workers', type=int, default=8, help='maximum number of dataloader workers')parser.add_argument('--project', default='runs/train', help='save to project/name')parser.add_argument('--entity', default=None, help='W&B entity')parser.add_argument('--name', default='exp', help='save to project/name')parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')parser.add_argument('--quad', action='store_true', help='quad dataloader')parser.add_argument('--linear-lr', action='store_true', help='linear LR')parser.add_argument('--label-smoothing', type=float, default=0.0, help='Label smoothing epsilon')parser.add_argument('--upload_dataset', action='store_true', help='Upload dataset as W&B artifact table')parser.add_argument('--bbox_interval', type=int, default=-1, help='Set bounding-box image logging interval for W&B')parser.add_argument('--save_period', type=int, default=-1, help='Log model after every "save_period" epoch')parser.add_argument('--artifact_alias', type=str, default="latest", help='version of dataset artifact to be used')opt = parser.parse_args()

训练自己的模型需要修改如下几个参数就可以训练了。首先将weights权重的路径填写到对应的参数里面,然后将修好好的models模型的yolov5s.yaml文件路径填写到相应的参数里面,最后将data数据的hat.yaml文件路径填写到相对于的参数里面。这几个参数就必须要修改的参数。

在这里插入图片描述

到了这一步差不多都可以,训练了

如果运行之后出现报错,直接百度即可,都是可以解决的

在这里插入图片描述

训练的时候,我们发现为啥这些指标都是0,通过一番捣鼓之后,发现是cuda的版本安装的不一样

通过一系列的排查纠错,最终终于发现了问题

在这里插入图片描述

如果在训练的时候,模型可以跑通,但是就是输出为0,给大家总结了一下几个原因:

  • 有可能是pytorch的cuda版本和你主机的版本不对应,但是这种情况一般出现的几率比较小
  • 建议在训练的时候统一模型参数,选择的时候需要注意有些参数需要修改,深度学习虽然不用写框架,但是参数也不是一成不变的,比如模型的超参数选择,用对应的权重的时候,有对应的参数需要修改。
    在这里插入图片描述
    这些都可以在官方仓库里面找到,然后修改对应的参数即可;比如第一个是权重文件,根据先验知识选择之后,然后修改对应的cfg文件,记住这里最好和权重选择的对应在一起,其次就是data.yaml文件修改

在这里插入图片描述在这里插入图片描述

这里可以选择不同的参数集

在这里插入图片描述
这里配置数据集的路径和标签

在这里插入图片描述

  • 数据的问题,注意维度是否一致,标签是否存在

训练参数详解

https://www.yht7.com/news/208540
https://zhuanlan.zhihu.com/p/366225937
https://zhuanlan.zhihu.com/p/516662016

启用tensorbord查看参数

yolov5里面有写好的tensorbord函数,可以运行命令就可以调用tensorbord,然后查看tensorbord了。首先打开pycharm的命令控制终端,输入如下命令,就会出现一个网址地址,将那行网址复制下来到浏览器打开就可以看到训练的过程了

切换到该工程路径下

tensorboard --logdir=runs/train

后面就可以让它慢慢训练了,然后进行测试

在这里插入图片描述

深度学习比较吃显卡,建议使用台式机跑,本人用的是3060

在这里插入图片描述

输出参数详解

https://blog.csdn.net/thy0000/article/details/125281995

https://www.cnblogs.com/Flat-White/p/14724045.html

每文一语

开始也是一种学习


http://www.ppmy.cn/news/617226.html

相关文章

Hexo 个人博客搭建完整版笔记

前言 2022-06-22&#xff0c;成都&#xff0c;夜晚&#xff0c;下雨&#xff0c;个人博客搭建完毕&#xff01;个人博客链接在此&#xff0c;欢迎访问~ 第一部分根据 搭建笔记 中的方法完成 Hexo Shoka 主题 Github 博客部署。 2022-07-02&#xff0c;成都&#xff0c;下午…

电脑日常维护十必须

本文中清除垃圾的运行命令,我已经用我的笔记本试验过了,有需要的同志可以放心大胆的使用!如果有问题的话我的笔记本也就挂啦!

二、代码实现深度学习道路训练样本数据的制作(代码部分详解)——重复工作+多次返工的血泪史

使用python读取文件夹对图片进行批量裁剪 通过第一部分操作arcgis制作了一部分样本数据 分辨率与原相片保持一致 为6060*6060 具体如图所示&#xff1a; 而我们深度学习一般使用的分辨率是1024和512的 这两个数字都无法整除6060 因此我在这里选择裁剪成606 代码参考了这篇博…

一文搞定Windows11+WSL+Pycharm开发环境及避坑

WSL+Pycharm开发环境搭建以及常见问题处理(Windows11) 零. 环境及背景0.1 为什么需要这样的开发环境0.2 什么是WSL0.3 搭建环境壹. Windows11 搭建WSL1.1 启动 WSL1.2 启动虚拟机平台功能:1.3 下载并安装Linux 内核更新包:1.4 将WSL2设置为默认版本:1.5 选择Linux发行版进…

这样做电脑速度回到当初刚买时

这样做电脑速度回到当初刚买时 2011年12月09日 [b]经过这样的保养&#xff0c;你的电脑是不是恢复了刚买时候的速度&#xff1f;甚至更快了&#xff0c;呵呵&#xff01;然后右键单击“我的电脑”&#xff0c;选择“属性”&#xff0c;再选择“性能”&#xff0c;看一下“系统…

live2d怎么移动_使用Live Mesh在计算机和移动设备之间同步文件

live2d怎么移动 Would you like to be able to access your files instantly from anywhere? With Live Mesh you can sync files between computers, mobile devices, and even Macs which is both free and easy. 您想随时随地访问文件吗&#xff1f; 使用Live Mesh&…

Windows / Ubuntu操作系统下Pixhawk原生固件PX4的编译方法

更新于2017.3.13 FAQ 本文说明针对 PX4 Firmware 1.6.0 问题 1&#xff1a; 找不到python jinja2模块 CMake Error at /usr/share/cmake-3.2/Modules/FindPackageHandleStandardArgs.cmake:138 (message):couldnt find python module jinja2:for debian systems try: s…

jetson xavier jetPack4.2刷机,安装tensorflow,安装pytorch,安装ros,编译python3版本cv_bridge

1. Jetson Xavier开箱与初始化 1) 为Jetson Xavier安装显示器和鼠标键盘 2) 连上电源&#xff0c;点击S501 power button(三个按钮中正置左数第一个), power led白灯常亮 3) 进入命令行界面安装操作系统ubuntu 18.04&#xff0c;初始账号和密码都是nvidia, 输入以下…