真香!全场景AI计算开源框架MindSpore,我爱了
【摘要】 本文主要通过两个实际应用案例:一是基于本地 Jupyter Notebook 的 MNIST 手写数据识别;二是基于华为云服务器的 CIFAR-10 图像分类,对开源框架 MindSpore 进行介绍。
犹记得今年的华为开发者大会 HDC 2020 上,一直受人瞩目的深度学习框架 MindSpore 终于开源了。
我之前一直关注 MindSpore,还是挺期待的。MindSpore 是一款支持端、边、云独立/协同的统一训练和推理框架。与 TensorFlow、PyTorch 等流行深度学习框架对标,MindSpore 旨在大幅度降低 AI 应用开发门槛,让人工智能无处不在。
MindSpore 最大的特点就是开发门槛大大降低,提高开发效率,这样可以显著减少模型开发时间。
因此,使用MindSpore的优势可以总结为以下四点:
●简单的开发体验
●灵活的调试模式
●充分发挥硬件潜能
●全场景快速部署
既然开源了,那就赶紧上手,试一试这款开源的 MindSpore 怎么样!本文我将介绍 MindSpore 的安装和上手教程,通过一个简单的图像识别案例来跑完整个 AI 训练和测试流程。
一、MindSpore 的安装
开源框架 MindSpore 的安装方法有很多,可以在 Windows、Ubuntu 上安装,也可以在华为 Ascend 910 上安装。各种详尽的安装方法请见下面的链接:
https://www.mindspore.cn/install
下面介绍两种最简单的安装方法!
1. Docker 安装
Docker 安装最为简单,可参考:
https://gitee.com/mindspore/mindspore#docker-image
以 0.3.0-alpha 版本为例:
- CPU:
docker pull mindspore/mindspore-cpu:0.3.0-alpha
- GPU:
docker pull mindspore/mindspore-gpu:0.3.0-alpha
安装好后,可以看到安装的镜像,并使用下面的命令创建一个你的容器:
docker run -it mindspore/mindspore-cpu:0.3.0-alpha /bin/bash
2. Win10+Anaconda+MindSpore
使用 Win10 +Anaconda+MindSpore 的方式进行安装也非常简单,本文将采用这种方式安装 MindSpore。
在 MindSpore 安装首页里,选择安装相关配置:
- 版本:0.3.0-alpha
- 硬件平台:CPU
- 操作系统:Windows-64
- 编程语言:Python 3.7.5
首先,在 Win10 上安装 Anaconda,Anaconda 是一个开源的 Python 发行版本,其包含了 conda、Python 等 180 多个科学包及其依赖项。
然后,创建一个虚拟环境。
1). 打开 Anaconda 组件中的 Anaconda Prompt 终端:
2). 使用下面的命令,创建一个虚拟环境 mindspore(名字可以自定义),并进入虚拟环境:
conda create -n mindspore python=3.7.5
conda activate mindspore
3). 安装依赖库,根据 https://gitee.com/mindspore/mindspore/blob/r0.3/requirements.txt 列出的依赖库,使用 conda 命令安装。例如:
conda install numpy
4). 根据之前选择的相关配置,在网站:https://www.mindspore.cn/versions 中选择所要相应的 MindSpore 版本:
mindspore-0.3.0-cp37-cp37m-win_amd64.whl
可以将.whl 文件下载到本地,使用 pip 安装(使用 conda 命令在线安装速度可能比较慢,因此可以选择将.whl文件下载到本地,使用 pip 命令安装):
pip install mindspore-0.3.0-cp37-cp37m-win_amd64.whl
最后测试是否安装成功,进入 Python shell,执行如下命令,如果没有提示 No module named 'mindspore' 等加载错误的信息,则说明安装成功。
至此,安装完成!
二、基于本地 Jupyter 实现 MNIST 手写数据集分类
1. 安装 Jupyter Notebook
首先,在虚拟环境 mindspore 中安装 Jupyter Notebook。方法是:打开 Anaconda 组件 Anaconda Navigator。
在 Anaconda Navigator 中,Application on 选择刚建立的虚拟环境 mindspore,在组件 Jupyter Notebook 下点击 install,安装。安装完成后如下图:
点击 Notebook 下的 Launch,即可打开 Jupyter Notebook。
2. 下载数据集
MNIST 手写数据集想必大家都很熟悉了,包含 0-9 的数字,由 60000 张训练图片和 10000 张测试图片组成。
MNIST 数据集下载页面:
http://yann.lecun.com/exdb/mnist/
使用 MindSpore,我们可以通过直接定义一个 download_dataset 函数来自动下载 MNIST 数据集:
def download_dataset():"""Download the dataset from http://yann.lecun.com/exdb/mnist/."""print("******Downloading the MNIST dataset******")train_path = "./MNIST_Data/train/"test_path = "./MNIST_Data/test/"train_path_check = os.path.exists(train_path)test_path_check = os.path.exists(test_path)if train_path_check == False and test_path_check ==False:os.makedirs(train_path)os.makedirs(test_path)train_url = {"http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz", "http://yann.lecun.com/exdb/mnist/train-labels-idx1-ubyte.gz"}test_url = {"http://yann.lecun.com/exdb/mnist/t10k-images-idx3-ubyte.gz", "http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz"}for url in train_url:url_parse = urlparse(url)# split the file name from urlfile_name = os.path.join(train_path,url_parse.path.split('/')[-1])if not os.path.exists(file_name.replace('.gz','')):file = urllib.request.urlretrieve(url, file_name)unzipfile(file_name)os.remove(file_name)for url in test_url:url_parse = urlparse(url)# split the file name from urlfile_name = os.path.join(test_path,url_parse.path.split('/')[-1])if not os.path.exists(file_name.replace('.gz','')):file = urllib.request.urlretrieve(url, file_name)unzipfile(file_name)os.remove(file_name)
该函数实现将数据集自动下载在本地的 ./MNIST_Data 目录下,训练集放在子目录 /train 下,测试集放在子目录 /test 下。
3. 数据预处理
MNIST 数据集准备好了之后,下一步就要对数据集进行一些预处理,包括图片尺寸调整为 32x32(因为我们使用的是 LeNet-5 网络,后面会介绍),像素归一化、batch_size 设为 32(可调整),等等。
MindSpore 提供了 mindspore.dataset.MnistDataset 来直接定义 Minist 数据集,非常方便。使用 mindspore.dataset.MnistDataset.map 映射函数,将数据操作应用到数据集。
我们定义 create_dataset() 函数来创建数据集:
def create_dataset(data_path, batch_size=32, repeat_size=1,num_parallel_workers=1):""" create dataset for train or testArgs:data_path: Data pathbatch_size: The number of data records in each grouprepeat_size: The number of replicated data recordsnum_parallel_workers: The number of parallel workers""" # define datasetmnist_ds = ds.MnistDataset(data_path)# define operation parametersresize_height, resize_width = 32, 32rescale = 1.0 / 255.0shift = 0.0rescale_nml = 1 / 0.3081shift_nml = -1 * 0.1307 / 0.3081# define map operationsresize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR) # Resize images to (32, 32)rescale_nml_op = CV.Rescale(rescale_nml, shift_nml) # normalize imagesrescale_op = CV.Rescale(rescale, shift) # rescale imageshwc2chw_op = CV.HWC2CHW() # change shape from (height, width, channel) to (channel, height, width) to fit network.type_cast_op = C.TypeCast(mstype.int32) # change data type of label to int32 to fit network# apply map operations on imagesmnist_ds = mnist_ds.map(input_columns="label", operations=type_cast_op, num_parallel_workers=num_parallel_workers)mnist_ds = mnist_ds.map(input_columns="image", operations=resize_op, num_parallel_workers=num_parallel_workers)mnist_ds = mnist_ds.map(input_columns="image", operations=rescale_op, num_parallel_workers=num_parallel_workers)mnist_ds = mnist_ds.map(input_columns="image", operations=rescale_nml_op, num_parallel_workers=num_parallel_workers)mnist_ds = mnist_ds.map(input_columns="image", operations=hwc2chw_op, num_parallel_workers=num_parallel_workers)# apply DatasetOpsbuffer_size = 10000mnist_ds = mnist_ds.shuffle(buffer_size=buffer_size) # 10000 as in LeNet train scriptmnist_ds = mnist_ds.batch(batch_size, drop_remainder=True)mnist_ds = mnist_ds.repeat(repeat_size)return mnist_ds
通过上面的函数,就完成了对刚下载的 MNIST 数据集的预处理。
4. 定义网络
LeNet-5 是一种用于手写体字符识别的非常高效的卷积神经网络。LeNet-5 共有 7 层,不包含输入,每层都包含可训练参数;每个层有多个 Feature Map,每个 FeatureMap通过一种卷积滤波器提取输入的一种特征。
1) 模型初始化
使用 mindspore.common.initializer.TruncatedNormal 方法对参数进行初始化,定义 conv 和 fc_with_initialize 分别对卷积层和全连接层进行初始化。
import mindspore.nn as nnfrom mindspore.common.initializer import TruncatedNormal
def conv(in_channels, out_channels, kernel_size, stride=1, padding=0): """Conv layer weight initial.""" weight = weight_variable() return nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, stride=stride, padding=padding, weight_init=weight, has_bias=False, pad_mode="valid")
def fc_with_initialize(input_channels, out_channels): """Fc layer weight initial.""" weight = weight_variable() bias = weight_variable() return nn.Dense(input_channels, out_channels, weight, bias)
def weight_variable(): """Weight initial.""" return TruncatedNormal(0.02)
使用 mindspore.common.initializer.TruncatedNormal 方法,可以非常便捷地实现网络权重系数的初始化操作,不需要自定义初始化函数。
2) 定义 LeNet-5 网络
MindSpore 来定义 LeNet-5 网络也很简单,根据网络结构,定义相应的卷积层和全连接层即可。在初始化函数 __init__ 种定义神经网络的各层,然后通过定义 construct 方法来完成神经网络的前向构造。
class LeNet5(nn.Cell): """Lenet network structure.""" # define the operator required def __init__(self): super(LeNet5, self).__init__() self.conv1 = conv(1, 6, 5) self.conv2 = conv(6, 16, 5) self.fc1 = fc_with_initialize(16 * 5 * 5, 120) self.fc2 = fc_with_initialize(120, 84) self.fc3 = fc_with_initialize(84, 10) self.relu = nn.ReLU() self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2) self.flatten = nn.Flatten()# use the preceding operators to construct networks def construct(self, x): x = self.conv1(x) x = self.relu(x) x = self.max_pool2d(x) x = self.conv2(x) x = self.relu(x) x = self.max_pool2d(x) x = self.flatten(x) x = self.fc1(x) x = self.relu(x) x = self.fc2(x) x = self.relu(x) x = self.fc3(x) return x
LeNet-5 是一个非常典型且简单的卷积神经网络,从 construct 方法可以详细看到 LeNet-5 各层的结构。
3) 定义损失函数
MindSpore 支持的损失函数有 SoftmaxCrossEntropyWithLogits、L1Loss、MSELoss 等。这里使用 SoftmaxCrossEntropyWithLogits 交叉熵损失函数。
from mindspore.nn.loss import SoftmaxCrossEntropyWithLogits
# define the loss functionnet_loss = SoftmaxCrossEntropyWithLogits(is_grad=False, sparse=True, reduction='mean')
4) 定义网络梯度下降算法
MindSpore 支持的梯度下降算法有 Adam、AdamWeightDecay、Momentum 等。这里使用流行的 Momentum 算法。其中,学习率设为 0.01,momentum 参数设为 0.9。
# learning rate setting
lr = 0.01
momentum = 0.9
# define the optimizer
net_opt = nn.Momentum(network.trainable_params(), lr, momentum)
5. 训练网络1) 模型保存mindspore.train.callback.ModelCheckpoint 方法可以保存网络模型和参数。config_ck = CheckpointConfig(save_checkpoint_steps=1875, keep_checkpoint_max=10)
# save the network model and parameters for subsequence fine-tuning
ckpoint_cb = ModelCheckpoint(prefix="checkpoint_lenet", config=config_ck)
2) 训练网络
训练网络使用 model.train 方法进行。这里把 epoch_size 设置为 1,对数据集进行 1 个迭代的训练。训练的过程中会打印 loss 值的变化。
from mindspore.nn.metrics import Accuracyfrom mindspore.train.callback import LossMonitorfrom mindspore.train import Model
def train_net(args, model, epoch_size, mnist_path, repeat_size, ckpoint_cb, sink_mode): """define the training method""" print("============== Starting Training ==============") #load training dataset ds_train = create_dataset(os.path.join(mnist_path, "train"), 32, repeat_size) model.train(epoch_size, ds_train, callbacks=[ckpoint_cb, LossMonitor()], dataset_sink_mode=sink_mode)
epoch_size = 1
mnist_path = "./MNIST_Data
# group layers into an object with training and evaluation features
model = Model(network, net_loss, net_opt, metrics={"Accuracy": Accuracy()})
train_net(args, model, epoch_size, mnist_path, repeat_size, ckpoint_cb)
其中,mnist_path 是 MNIST 数据集路径。
3) 硬件信息
在主函数中,别忘了配置 MindSpore 运行的硬件信息。因为我们是在 CPU 环境下,所以 ‘--device_target’ 设置为 “CPU”。
parser = argparse.ArgumentParser(description='MindSpore LeNet Example')
parser.add_argument('--device_target', type=str, default="CPU", choices=['Ascend', 'GPU', 'CPU'],help='device where the code will be implemented (default: CPU)')
args = parser.parse_args(args=[])
context.set_context(mode=context.GRAPH_MODE, device_target=args.device_target)
这里的 '--device_target' 默认是 “CPU”,根据硬件情况也可以选择 “Ascend” 或 “GPU”。使用的是图模式 “context.GRAPH_MODE”。
4) 模型训练
执行程序,模型训练开始。训练过程中会打印 loss 值:
...
epoch: 1 step: 262, loss is 1.9212162
epoch: 1 step: 263, loss is 1.8498616
epoch: 1 step: 264, loss is 1.7990671
epoch: 1 step: 265, loss is 1.9492403
epoch: 1 step: 266, loss is 2.0305142
epoch: 1 step: 267, loss is 2.0657792
epoch: 1 step: 268, loss is 1.9582214
epoch: 1 step: 269, loss is 0.9459006
epoch: 1 step: 270, loss is 0.8167224
epoch: 1 step: 271, loss is 0.7432692
...
可以看到 loss 总体来说会逐步减小,精度逐步提高,最终的 loss 为 0.067。
训练完成之后,得到保存的模型文件:
checkpoint_lenet-1_1875.ckpt
6. 模型测试
在得到模型文件后,使用 model.eval() 接口读入测试数据集,通过模型运行测试数据集得到的结果。定义测试函数 test_net():
def test_net(args, network, model, mnist_path):"""Define the evaluation method."""print("============== Starting Testing ==============")# load the saved model for evaluationparam_dict = load_checkpoint("checkpoint_lenet-1_1875.ckpt")# load parameter to the networkload_param_into_net(network, param_dict)# load testing datasetds_eval = create_dataset(os.path.join(mnist_path, "test"))acc = model.eval(ds_eval, dataset_sink_mode=False)print("============== Accuracy:{} ==============".format(acc))
运行测试网络:
test_net(args, network, model, mnist_path)
============== Starting Testing ==============
============== Accuracy:{'Accuracy': 0.9663461538461539} ==============
最终,可以看到刚刚训练的 LeNet-5 网络模型在测试集上的精度是 96.63%,效果非常不错。
至此,我们使用 MindSpore 框架训练 LeNet-5 模型已经完成。实现了基于本地 Jupyter 实现 MNIST 手写数据集分类。总的来说,MindSpore 提供了很多模块化的方法来进行模型搭建和训练,非常方便我们能够快速搭建一个神经网络模型。大家可以根据自己实际需求,上手搭建一个自己的神经网络试试。
本节完整代码:
https://gitee.com/mindspore/docs/blob/master/tutorials/tutorial_code/lenet.py
三、在云服务器上使用 MindSpore
除了可以在本地使用 MindSpore 框架之外,我们还可以在华为云服务器上使用 MindSpore。在华为云上使用 MindSpore 的还有一个好处是,我们可以申请使用昇腾 AI 处理器资源池作为硬件。
ModelArts 是华为云提供的面向开发者的一站式 AI 开发平台,而且集成了 MindSpore。下面我们将在 ModelArts 下使用 ResNet-50 网络识别 CIFAR-10 图片。
1. 准备 ModelArts
1) 进入华为云官网,注册账号。
具体操作:
https://support.huaweicloud.com/prepare-modelarts/modelarts_08_0001.html
2) 获取访问密钥并完成 ModelArts 配置。
具体操作:
https://support.huaweicloud.com/prepare-modelarts/modelarts_08_0002.html
3) 创建 OBS 桶
具体操作:
https://support.huaweicloud.com/prepare-modelarts/modelarts_08_0003.html
2. 申请服务器昇腾 AI 处理器资源
为了在 ModelArts 上使用华为云昇腾 AI 处理器,我们需要申请体验资格,申请方式也很简单,可在下面的网站上进行申请:
https://console.huaweicloud.com/modelarts/?region=cn-north-4#/dashboard/applyModelArtsAscend910Beta
申请时的内容大家可以填仔细些,一般正常的话两个工作日就批下来了。
3. 数据准备
1) 下载 CIFAR-10 数据集
CIFAR-10 该数据集共有 60000 张彩***像,这些图像是 32*32,分为 10 个类,每类 6000 张图。
CIFAR-10 数据集下载地址:
http://www.cs.toronto.edu/~kriz/cifar.html
注意下载 CIFAR-10 binary version 版本。
2) 新建一个自己的 OBS 桶(例如:mine-ms-dataset)
ModelArts 使用对象存储服务(Object Storage Service,简称 OBS)进行数据存储,因此,在开始训练任务之前,需要将数据上传至 OBS。
首先,登录 OBS 管理控制台:
https://storage.huaweicloud.com/obs/?region=cn-north-4#/obs/manager/buckets
创建 OBS 桶 mine-ms-dataset(名称可修改,下面类似)。
然后,在刚创建的 OBS 桶里,创建用于存放数据的文件夹:在桶列表单击待操作的桶,在左侧导航栏,单击“对象”,新建文件夹 mine-cifar-10。
最后,将下载好的 CIFAR-10 数据集按照以下目录结构上传至数据目录 mine-cifar-10 中:
└─对象存储/mine-ms-dataset/mine-cifar-10├─train│ data_batch_1.bin│ data_batch_2.bin│ data_batch_3.bin│ data_batch_4.bin│ data_batch_5.bin│└─evaltest_batch.bin
4. 程序准备
新建一个 OBS 桶(例如:mine-resnet50-train),在桶中创建代码目录(例如:mine-resnet50_cifar10_train)。同时在该桶中创建 output 目录和 log 目录,用来存放模型和日志。
将网址:
https://gitee.com/mindspore/docs/tree/master/tutorials/tutorial_code/sample_for_cloud/
中的两个 .py 文件 dataset.py 和 resnet50_train.py 下载并上传到代码目录 mine-resnet50_cifar10_train 中。
代码目录 mine-resnet50_cifar10_train 结构如下:
└─对象存储/mine-resnet50-train├─mine-resnet50_cifar10_train│ dataset.py│ resnet50_train.py│├─output└─log
5. 创建训练任务
准备好数据和执行脚本以后,下面就可以在云服务器上创建训练任务了。
1) 进入 ModelArts 控制台
打开华为云 ModelArts 主页
https://www.huaweicloud.com/product/modelarts.html
点击“进入控制台”。
2) 使用 MindSpore 作为常用框架创建训练作业
在左侧导航栏中选择“训练管理 > 训练作业”,默认进入“训练作业”列表。
在训练作业列表中,单击左上角“创建”,进入“创建训练作业”页面。
在创建训练作业页面,训练作业名称自定义,例如 mine-resnet50-trainjob。填写训练作业相关参数,具体配置参数如下:
值得注意的时,算法来源常用框架选择 Ascend-Powered-Engine,因为我们使用的是硬件是华为云昇腾 AI 处理器。MindSpore 版本选择 MindSpore-0.1-python3.7-aarch64 即可。
配置完之后,点击下一步 -> 提交 -> 返回训练作业列表,可以看到训练作业 mine-resnet50-trainjob 正在运行:
整个运行过程大概 8 分半钟,显示运行成功,表示模型训练测试完成。
最后,点击训练作业 mine-resnet50-trainjob,在日志里可以看到模型在测试集上的准确率为 92.49%,说明该模型效果不错。
我们还可以从 OBS 种下载日志文件并查看。
以上就是在云上使用 MindSpore 的简单教程。
四、总结
从我个人的使用感觉来看,MindSpore 用起来还是很顺手的,而且函数封装得比较简洁,使用起来较为方便。通过手把手的教程,大家完全可以自己动手实操一下,感受一下开源框架 MindSpore 的魅力。
大家也可以根据自己的具体应用场景和实用案例,使用 MindSpore,搭建神经网络模型,解决实际问题。无论是计算机视觉还是自然语言处理,相信 MindSpore 都能给大家带来流畅的体验。
参考资料:
https://www.mindspore.cn/
https://www.mindspore.cn/tutorial/zh-CN/master/index.html
https://support.huaweicloud.com/modelarts/index.html
点击这里→了解更多精彩内容
相关推荐
解密如何使用昇腾AI计算解决方案构建业务引擎
【玩转Atlas200DK系列】基于Pycharm专业版构建开发板python开发运行环境
【玩转Atlas200DK系列】Atlas 200 DK安装python的hiai库以及opencv
解密昇腾AI处理器--DaVinci架构(计算单元)
真香!全场景AI计算开源框架MindSpore,我爱了相关推荐
- 刚刚,华为全场景 AI 计算框架MindSpore正式开源!国产深度学习框架的春天来了!...
关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 此前,我们刚刚报道了旷视科技在3月25日开源深度学习框架 MegEngine ,3 ...
- 华为正式宣布全场景AI计算框架MindSpore开源 降低AI开发门槛
今日,在华为开发者大会2020(Cloud)第二天,华为宣布全场景AI计算框架MindSpore在码云正式开源,企业级AI应用开发者套件ModelArts Pro在华为云上线.华为全栈全场景AI解决方 ...
- 华为全场景AI计算框架MindSpore正式开源,赋能开发者昇腾万里
[中国,深圳,2020年3月28日]今日,在华为开发者大会2020(Cloud)第二天,华为宣布全场景AI计算框架MindSpore在码云正式开源,企业级AI应用开发者套件ModelArts Pro在 ...
- 什么是全场景AI计算框架MindSpore?
摘要:MindSpore是华为公司推出的新一代深度学习框架,是源于全产业的最佳实践,最佳匹配昇腾处理器算力,支持终端.边缘.云全场景灵活部署,开创全新的AI编程范式,降低AI开发门槛. MindSpo ...
- 华为发布最强 AI 处理器昇腾 910,全场景 AI 框架 MindSpore 将开源
整理 | 胡巍巍 好巧呀好巧,前几天刚参观完华为北京研究所,一睹昇腾310 AI处理器的真容,今儿个昇腾910就来了. 昇腾310 AI处理器,摄于华为北京研究所 8月23日,华为正式发布AI处理器A ...
- 昇思MindSpore全场景AI框架 1.6版本,更高的开发效率,更好地服务开发者
本文分享自华为云社区<昇思MindSpore全场景AI框架 1.6版本,更高的开发效率,更好地服务开发者>,作者: 技术火炬手. 全新的昇思MindSpore全场景AI框架1.6版本已发布 ...
- 应对全场景AI框架部署挑战,MindSpore“四招”让你躺平
摘要:所谓全场景AI,是指可以将深度学习技术快速应用在云边端不同场景下的硬件设备上,包括云服务器.移动终端以及IoT设备等等,高效运行并能有效协同. 本文分享自华为云社区<AI框架的挑战与Min ...
- 边缘计算开源框架EdgeXFoundry的部署应用开发(三)设备服务开发
边缘计算开源框架EdgeXFoundry的部署应用开发(三)设备服务开发 使用SDK开发真实设备接入服务 着手编写一个温湿度设备接入 准备相关文件及目录 脚本可选,用于单文件编译测试 编写温湿度设备接 ...
- 全场景AI推理引擎MindSpore Lite, 助力HMS Core视频编辑服务打造更智能的剪辑体验
移动互联网的发展给人们的社交和娱乐方式带来了很大的改变,以vlog.短视频等为代表的新兴文化样态正受到越来越多人的青睐.同时,随着AI智能.美颜修图等功能在图像视频编辑App中的应用,促使视频编辑效率 ...
最新文章
- python 判断debug
- WPF WindowStyle为None
- windows mysql状态_windows下使用mysql双机热备功能
- mysql cmake 参数详解
- 计算机在学前教育和美术绘画中的应用,幼儿园美术教学活动中信息技术的应用...
- 互联网日报 | 3月12日 星期五 | 京东全年净增1.1亿活跃用户;百度计划3月23日登陆港交所;中国联通首次公布5G用户数...
- [Unity] StartCoroutine 无法启动协程的可能原因:没有使用 AddComponent<T>() 初始化 Monobehaviour
- Linux——通配符
- Linux Ubuntu 18.04安装JDK、Hadoop、Hbase以及图形界面
- 15.分布式文档系统-document id的手动指定与自动生成两种方式解析
- 猿编程python,python编程猿
- mysql服务器无法启动
- c语言实现一个密码管理器(更新中)
- 笔记本HDMI1.4 1080p下外接高刷显示器的实现方法之一
- 深入浅出的CSS项目开发总结
- DFS和BFS求字符串的所有非空子集———Java
- 2019.12.31罗振宇2020年跨年演讲《时间的朋友》精华全文版本——思维决定一个人的上限,能力决定一个人的下限
- TOJ 1717 WOJ
- 你会查杀病毒吗?反病毒技巧! 比较长。
- dhtml是基于html的一门语言,用户直接使用集成的动态HTML语言(简称DHTML)来开发基于.ppt...