{ "cells": [ { "cell_type": "markdown", "id": "fa7e3e52", "metadata": {}, "source": [ "# ResNet50图像分类\n", "\n", "[![下载Notebook](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_notebook.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/master/tutorials/application/zh_cn/cv/mindspore_resnet50.ipynb) [![下载样例代码](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_download_code.svg)](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/master/tutorials/application/zh_cn/cv/mindspore_resnet50.py) [![查看源文件](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/resource/_static/logo_source.svg)](https://gitee.com/mindspore/docs/blob/master/tutorials/application/source_zh_cn/cv/resnet50.ipynb)\n", "\n", "图像分类是最基础的计算机视觉应用,属于有监督学习类别,如给定一张图像(猫、狗、飞机、汽车等等),判断图像所属的类别。本章将介绍使用ResNet50网络对CIFAR-10数据集进行分类。\n", "\n", "## ResNet网络介绍\n", "\n", "ResNet50网络是2015年由微软实验室的何恺明提出,获得ILSVRC2015图像分类竞赛第一名。在ResNet网络提出之前,传统的卷积神经网络都是将一系列的卷积层和池化层堆叠得到的,但当网络堆叠到一定深度时,就会出现退化问题。下图是在CIFAR-10数据集上使用56层网络与20层网络训练误差和测试误差图,由图中数据可以看出,56层网络比20层网络训练误差和测试误差更大,随着网络的加深,其误差并没有如预想的一样减小。\n", "\n", "![resnet-1](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/tutorials/application/source_zh_cn/cv/images/resnet_1.png)\n", "\n", "ResNet网络提出了残差网络结构(Residual Network)来减轻退化问题,使用ResNet网络可以实现搭建较深的网络结构(突破1000层)。论文中使用ResNet网络在CIFAR-10数据集上的训练误差与测试误差图如下图所示,图中虚线表示训练误差,实线表示测试误差。由图中数据可以看出,ResNet网络层数越深,其训练误差和测试误差越小。\n", "\n", "![resnet-4](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/tutorials/application/source_zh_cn/cv/images/resnet_4.png)\n", "\n", "> 了解ResNet网络更多详细内容,参见[ResNet论文](https://arxiv.org/pdf/1512.03385.pdf)。" ] }, { "cell_type": "markdown", "id": "a987ee48", "metadata": {}, "source": [ "## 数据集准备与加载\n", "\n", "[CIFAR-10数据集](http://www.cs.toronto.edu/~kriz/cifar.html)共有60000张32*32的彩色图像,分为10个类别,每类有6000张图,数据集一共有50000张训练图片和10000张评估图片。首先,如下示例使用`download`接口下载并解压,目前仅支持解析二进制版本的CIFAR-10文件(CIFAR-10 binary version)。" ] }, { "cell_type": "code", "execution_count": 1, "id": "1f9b81fb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'./datasets-cifar10-bin'" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from download import download\n", "\n", "url = \"https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz\"\n", "\n", "download(url, \"./datasets-cifar10-bin\", kind=\"tar.gz\", replace=True)" ] }, { "cell_type": "markdown", "id": "7e9020ba", "metadata": {}, "source": [ "下载后的数据集目录结构如下:\n", "\n", "```text\n", "datasets-cifar10-bin/cifar-10-batches-bin\n", "├── batches.meta.text\n", "├── data_batch_1.bin\n", "├── data_batch_2.bin\n", "├── data_batch_3.bin\n", "├── data_batch_4.bin\n", "├── data_batch_5.bin\n", "├── readme.html\n", "└── test_batch.bin\n", "\n", "```\n", "\n", "然后,使用`mindspore.dataset.Cifar10Dataset`接口来加载数据集,并进行相关图像增强操作。" ] }, { "cell_type": "code", "execution_count": 2, "id": "df7fb621", "metadata": {}, "outputs": [], "source": [ "import mindspore as ms\n", "import mindspore.dataset as ds\n", "import mindspore.dataset.vision as vision\n", "import mindspore.dataset.transforms as transforms\n", "from mindspore import dtype as mstype\n", "\n", "data_dir = \"./datasets-cifar10-bin/cifar-10-batches-bin\" # 数据集根目录\n", "batch_size = 256 # 批量大小\n", "image_size = 32 # 训练图像空间大小\n", "workers = 4 # 并行线程个数\n", "num_classes = 10 # 分类数量\n", "\n", "\n", "def create_dataset_cifar10(dataset_dir, usage, resize, batch_size, workers):\n", "\n", " data_set = ds.Cifar10Dataset(dataset_dir=dataset_dir,\n", " usage=usage,\n", " num_parallel_workers=workers,\n", " shuffle=True)\n", "\n", " trans = []\n", " if usage == \"train\":\n", " trans += [\n", " vision.RandomCrop((32, 32), (4, 4, 4, 4)),\n", " vision.RandomHorizontalFlip(prob=0.5)\n", " ]\n", "\n", " trans += [\n", " vision.Resize(resize),\n", " vision.Rescale(1.0 / 255.0, 0.0),\n", " vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),\n", " vision.HWC2CHW()\n", " ]\n", "\n", " target_trans = transforms.TypeCast(mstype.int32)\n", "\n", " # 数据映射操作\n", " data_set = data_set.map(operations=trans,\n", " input_columns='image',\n", " num_parallel_workers=workers)\n", "\n", " data_set = data_set.map(operations=target_trans,\n", " input_columns='label',\n", " num_parallel_workers=workers)\n", "\n", " # 批量操作\n", " data_set = data_set.batch(batch_size)\n", "\n", " return data_set\n", "\n", "\n", "# 获取处理后的训练与测试数据集\n", "\n", "dataset_train = create_dataset_cifar10(dataset_dir=data_dir,\n", " usage=\"train\",\n", " resize=image_size,\n", " batch_size=batch_size,\n", " workers=workers)\n", "step_size_train = dataset_train.get_dataset_size()\n", "\n", "dataset_val = create_dataset_cifar10(dataset_dir=data_dir,\n", " usage=\"test\",\n", " resize=image_size,\n", " batch_size=batch_size,\n", " workers=workers)\n", "step_size_val = dataset_val.get_dataset_size()" ] }, { "cell_type": "markdown", "id": "21e86f95", "metadata": {}, "source": [ "对CIFAR-10训练数据集进行可视化。" ] }, { "cell_type": "code", "execution_count": 3, "id": "c3ffabb3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Image shape: (256, 3, 32, 32), Label shape: (256,)\n", "Labels: [3 2 7 6 0 4]\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAgMAAAGFCAYAAABg2vAPAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjYuMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/P9b71AAAACXBIWXMAAA9hAAAPYQGoP6dpAABz5klEQVR4nO29ebhlVXnn/+69z3zucO481K2699atoqoooMBiUAYLRCUIEkwEh04EnEBsjWntdEefCKKRTscE06RthyTg1E9HHLCNCk6FIoLMUFBQAzXfqrrzucOZz97794c/bvsOUiclUMP+fp4nT1yL9+xh7bXXWfe83/q+ThiGIQEAAAAgsrhH+gIAAAAAcGTBZgAAAACIONgMAAAAABEHmwEAAAAg4mAzAAAAAEQcbAYAAACAiIPNAAAAABBxsBkAAAAAIg42AwAAAEDEwWYAgOOEG2+8kRzHocnJyReMGxoaoquvvvr3Otf5559P559//u91DBAtGp2f4MiAzcDLxP79++nGG2+kxx9//EhfCgAAAMCIHekLiAr79++nT3ziEzQ0NESnnnrqkb4cEGG2bNlCrou/AwAA/w+sCABEjGQySfF4/AVjCoXCy3Q1ALw4hGFIpVLpSF/GMQs2Aw0wOjpK73rXu6i/v5+SySQNDw/T+973PqpWqzQ9PU0f+chH6OSTT6ampiZqaWmhiy++mJ544onFz99zzz10xhlnEBHRNddcQ47jkOM4dPvttx+hOwLHM5OTk3TllVdSS0sLdXR00J/92Z9RuVxe/O9SM3D77beT4zj085//nK6//nrq7u6mgYGBxf/+xS9+kUZGRiidTtOZZ55J995778t5O+A4I5/P09VXX025XI5aW1vpmmuuoWKxuPjf6/U6ffKTn6SRkRFKJpM0NDREH/3oR6lSqbDjDA0N0aWXXkp33303nX766ZROp+kLX/gCERH9+Mc/pnPPPZdyuRw1NTXRqlWr6KMf/Sj7fKVSoRtuuIFWrFhByWSSli5dSn/xF3+hzhMVkCY4BPv376czzzyT8vk8vfe976XVq1fT6OgoffOb36RisUg7duygO++8k6644goaHh6msbEx+sIXvkAbNmygzZs3U39/P61Zs4Zuuukm+vjHP07vfe976bzzziMiorPPPvsI3x04HrnyyitpaGiIbr75ZnrggQfof/yP/0EzMzP0la985QU/d/3111NXVxd9/OMfX/xl4J//+Z/p2muvpbPPPps+9KEP0Y4dO+iyyy6j9vZ2Wrp06ctxO+A448orr6Th4WG6+eab6dFHH6V/+qd/ou7ubvqbv/kbIiJ697vfTV/+8pfpzW9+M334wx+mX//613TzzTfTM888Q9/5znfYsbZs2UJve9vb6Nprr6X3vOc9tGrVKnr66afp0ksvpVNOOYVuuukmSiaTtH37drrvvvsWPxcEAV122WX0y1/+kt773vfSmjVraNOmTXTLLbfQ1q1b6c4773w5h+ToIAQvyDve8Y7Qdd3woYceUv8tCIKwXC6Hvu+z/p07d4bJZDK86aabFvseeuihkIjC22677aW+ZBBRbrjhhpCIwssuu4z1X3/99SERhU888UQYhmE4ODgYXnXVVYv//bbbbguJKDz33HPDer2+2F+tVsPu7u7w1FNPDSuVymL/F7/4xZCIwg0bNryk9wOOL56fn+985ztZ/5ve9Kawo6MjDMMwfPzxx0MiCt/97nezmI985CMhEYU/+9nPFvsGBwdDIgrvuusuFnvLLbeERBROTEz8zmv56le/GrquG957772s//Of/3xIROF99913WPd4LIM0wQsQBAHdeeed9MY3vpFOP/109d8dx6FkMrkoxvJ9n6amphZ/lnr00Udf7ksGgN7//vez9gc+8AEiIvrBD37wgp97z3veQ57nLbYffvhhGh8fp+uuu44SicRi/9VXX02tra0v4hWDKHHdddex9nnnnUdTU1M0Nze3OEf/03/6Tyzmwx/+MBERff/732f9w8PDdNFFF7G+XC5HRETf/e53KQgC8xruuOMOWrNmDa1evZomJycX/+81r3kNERFt3Ljx8G7uGAabgRdgYmKC5ubm6KSTTvqdMUEQ0C233EIrV66kZDJJnZ2d1NXVRU8++STNzs6+jFcLwG9YuXIla4+MjJDrurRr164X/Nzw8DBr79692zxePB6n5cuX//4XCiLJsmXLWLutrY2IiGZmZmj37t3kui6tWLGCxfT29lIul1uck88j5ywR0Vve8hY655xz6N3vfjf19PTQW9/6VvrGN77BNgbbtm2jp59+mrq6utj/nXDCCUREND4+/qLc67EENAO/J5/+9Kfpr/7qr+id73wnffKTn6T29nZyXZc+9KEP/c5dKQAvJ47jNBSXTqdf4isB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LqONGzfSu971Ljr11FPp7rvvpv/8n/8zjY6O0i233LJ47Kuvvpq+8Y1v0J/+6Z/SK1/5Svr5z39Ol1xyyRG8W3C08NBDD9GvfvUreutb30oDAwO0a9cu+l//63/R+eefT5s3b6ZMJvOCn5+amqKLL76Y3vrWt9Kf/MmfUE9Pz+J/27ZtG73lLW+h6667jq666iq67bbb6IorrqC77rqLXve61/3OY95xxx1ULBbpfe97H3V0dNCDDz5It956K+3bt4/uuOMOFuv7Pl100UV01lln0Wc+8xn6yU9+Qn/3d39HIyMj9L73vW8x7tprr6Xbb7+drrnmGvrgBz9IO3fupH/8x3+kxx57jO677z6Kx+OHOYLgWGXTpk30+te/nrq6uujGG2+ker1ON9xwA5vDRER//dd/TX/1V39FV155Jb373e+miYkJuvXWW+nVr341PfbYY4u/5P7sZz+jiy++mNavX0833HADua5Lt912G73mNa+he++9l84880x23CuuuIJWrlxJn/70p9UfcJEjBIyNGzeGRBTecccdi31XXXVVSEThf/2v/5XF3nnnnSERhZ/61KdY/5vf/ObQcZxw+/btYRiG4SOPPBISUfihD32IxV199dUhEYU33HDDS3Mz4JigWCyqvvvvvz8kovArX/nKYt/zc3Pjxo2LfRs2bAiJKPz85z+vjjE4OBgSUfitb31rsW92djbs6+sLTzvttBc8rnVNN998c+g4Trh79+7FvuffjZtuuonFnnbaaeH69esX2/fee29IROHXv/51FnfXXXeZ/SAaXH755WEqlWJzavPmzaHneeHzX0+7du0KPc8L//qv/5p9dtOmTWEsFlvsD4IgXLlyZXjRRReFQRAsxhWLxXB4eDh83etet9h3ww03hEQUvu1tb3spb++YAmmCfwe//VcOEdEPfvAD8jyPPvjBD7L+D3/4wxSGIf3whz8kIqK77rqLiIiuv/56FveBD3zgJbxacKyQTqcX/3etVqOpqSlasWIF5XI5evTRRw/5+WQySddcc4353/r7++lNb3rTYrulpYXe8Y530GOPPUYHDx5s6JoKhQJNTk7S2WefTWEY0mOPPabir7vuOtY+77zzaMeOHYvtO+64g1pbW+l1r3sdTU5OLv7f+vXrqampiTZu3HjI+wTHF77v0913302XX345LVu2bLF/zZo1dNFFFy22v/3tb1MQBHTllVeyudPb20srV65cnDuPP/44bdu2jd7+9rfT1NTUYlyhUKALL7yQfvGLX1AQBOwa5LyNMkgTNEgsFqOBgQHWt3v3burv76fm5mbWv2bNmsX//vz/d12XhoeHWdyKFStewisGxwqlUoluvvlmuu2222h0dJT9XDk7O3vIzy9ZsuR3/guDFStWqH+vfcIJJxAR0a5du6i3t9f83J49e+jjH/84/d//+39VTl9eUyqVoq6uLtbX1tbGPrdt2zaanZ2l7u5u83zPC3dBdJiYmKBSqUQrV65U/23VqlX0gx/8gIh+M3fCMDTjiGgxvbRt2zYiIrrqqqt+5zlnZ2epra1tsS3X5CiDzUCDJJPJQ6q4ATgcPvCBD9Btt91GH/rQh+hVr3oVtba2kuM49Na3vlX9JWPx23/Fvxj4vk+ve93raHp6mv7Lf/kvtHr1aspmszQ6OkpXX321uibP8w55zCAIqLu7m77+9a+b/11uJgB4niAIyHEc+uEPf2jOtaampsU4IqK//du/pVNPPdU81vOxz/NivzvHMtgM/B4MDg7ST37yE5qfn2e/Djz77LOL//35/x8EAe3cuZPtbrdv3/7yXjA4KvnmN79JV111Ff3d3/3dYl+5XKZ8Pv97H3v79u0UhiH7dWDr1q1E9Jt/bWCxadMm2rp1K335y1+md7zjHYv9P/7xjw/7OkZGRugnP/kJnXPOOViAARH9ZgOYTqcX/6L/bbZs2bL4v0dGRigMQxoeHl78VctiZGSEiH6TCnvta1/74l/wcQ7+1P09eMMb3kC+79M//uM/sv5bbrmFHMehiy++mIhoMf/1uc99jsXdeuutL8+FgqMaz/OUkvnWW29V/zTvcNi/fz995zvfWWzPzc3RV77yFTr11FN/Z4rg+b++fvuawjCkf/iHfzjs67jyyivJ93365Cc/qf5bvV5/UTY+4NjC8zy66KKL6M4776Q9e/Ys9j/zzDN09913L7b/6I/+iDzPo0984hPqPQnDkKampoiIaP369TQyMkKf+cxnaGFhQZ1vYmLiJbqT4wP8MvB78MY3vpEuuOAC+tjHPka7du2idevW0Y9+9CP67ne/Sx/60IcWd6rr16+nP/7jP6bPfvazNDU1tfhPC5//Cw0e3NHm0ksvpa9+9avU2tpKJ554It1///30k5/8hDo6On7vY59wwgn0rne9ix566CHq6emhf/mXf6GxsTG67bbbfudnVq9eTSMjI/SRj3yERkdHqaWlhb71rW/9Xn4AGzZsoGuvvZZuvvlmevzxx+n1r389xeNx2rZtG91xxx30D//wD/TmN7/5sI8Pjk0+8YlP0F133UXnnXceXX/99VSv1+nWW2+ltWvX0pNPPklEv/mL/1Of+hT95V/+Je3atYsuv/xyam5upp07d9J3vvMdeu9730sf+chHyHVd+qd/+ie6+OKLae3atXTNNdfQkiVLaHR0lDZu3EgtLS30ve997wjf8VHMEfpXDEctv+ufFmazWTN+fn4+/PM///Owv78/jMfj4cqVK8O//du/Zf+0JQzDsFAohO9///vD9vb2sKmpKbz88svDLVu2hEQU/rf/9t9e0nsCRzczMzPhNddcE3Z2doZNTU3hRRddFD777LPh4OBgeNVVVy3G/a5/Wrh27VrzuIODg+Ell1wS3n333eEpp5wSJpPJcPXq1Wxu/67jbt68OXzta18bNjU1hZ2dneF73vOe8IknngiJKLztttsW437Xu/H8P92SfPGLXwzXr18fptPpsLm5OTz55JPDv/iLvwj379/f2GCB446f//zn4fr168NEIhEuX748/PznP2/On29961vhueeeG2az2TCbzYarV68O3//+94dbtmxhcY899lj4R3/0R2FHR0eYTCbDwcHB8Morrwx/+tOfLsY8f/yJiYmX5R6PBZwwjLrTwpHj8ccfp9NOO42+9rWvLToaAvBiMTQ0RCeddBL927/925G+FADAUQ40Ay8T0saViOizn/0sua5Lr371q4/AFQEAAAC/AZqBl4n//t//Oz3yyCN0wQUXUCwWox/+8If0wx/+kN773vfS0qVLj/TlAQAAiDDYDLxMnH322fTjH/+YPvnJT9LCwgItW7aMbrzxRvrYxz52pC8NAABAxIFmAAAAAIg40AwAAAAAEQebAQAAACDiNKwZgDEOeDE4ElmpRubu7EJF9dXrddYuV3XMF2+/nbW3P/ecikmKIkKhcT2BX1d9nTluOrRqpS5s9aY3XSLOFVcxjqipkfD0ax93D11foCGM5+uLWgZWvQVZ98PzrL9TDv0cQ7LmF/9cYF1jyGOso6S8l38NxLoLXgwaWXfxywAAAAAQcbAZAAAAACIONgMAAABAxMFmAAAAAIg4MB0CgIiK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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "\n", "data_iter = next(dataset_train.create_dict_iterator())\n", "\n", "images = data_iter[\"image\"].asnumpy()\n", "labels = data_iter[\"label\"].asnumpy()\n", "print(f\"Image shape: {images.shape}, Label shape: {labels.shape}\")\n", "\n", "# 训练数据集中,前六张图片所对应的标签\n", "print(f\"Labels: {labels[:6]}\")\n", "\n", "classes = []\n", "\n", "with open(data_dir + \"/batches.meta.txt\", \"r\") as f:\n", " for line in f:\n", " line = line.rstrip()\n", " if line:\n", " classes.append(line)\n", "\n", "# 训练数据集的前六张图片\n", "plt.figure()\n", "for i in range(6):\n", " plt.subplot(2, 3, i + 1)\n", " image_trans = np.transpose(images[i], (1, 2, 0))\n", " mean = np.array([0.4914, 0.4822, 0.4465])\n", " std = np.array([0.2023, 0.1994, 0.2010])\n", " image_trans = std * image_trans + mean\n", " image_trans = np.clip(image_trans, 0, 1)\n", " plt.title(f\"{classes[labels[i]]}\")\n", " plt.imshow(image_trans)\n", " plt.axis(\"off\")\n", "plt.show()" ] }, { "cell_type": "markdown", "id": "76c96f76", "metadata": {}, "source": [ "## 构建网络\n", "\n", "残差网络结构(Residual Network)是ResNet网络的主要亮点,ResNet使用残差网络结构后可有效地减轻退化问题,实现更深的网络结构设计,提高网络的训练精度。本节首先讲述如何构建残差网络结构,然后通过堆叠残差网络来构建ResNet50网络。\n", "\n", "### 构建残差网络结构\n", "\n", "残差网络结构图如下图所示,残差网络由两个分支构成:一个主分支,一个shortcuts(图中弧线表示)。主分支通过堆叠一系列的卷积操作得到,shotcuts从输入直接到输出,主分支输出的特征矩阵$F(x)$加上shortcuts输出的特征矩阵$x$得到$F(x)+x$,通过Relu激活函数后即为残差网络最后的输出。\n", "\n", "![residual](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/tutorials/application/source_zh_cn/cv/images/resnet_3.png)\n", "\n", "残差网络结构主要由两种,一种是Building Block,适用于较浅的ResNet网络,如ResNet18和ResNet34;另一种是Bottleneck,适用于层数较深的ResNet网络,如ResNet50、ResNet101和ResNet152。\n", "\n", "#### Building Block\n", "\n", "Building Block结构图如下图所示,主分支有两层卷积网络结构:\n", "\n", "+ 主分支第一层网络以输入channel为64为例,首先通过一个$3\\times3$的卷积层,然后通过Batch Normalization层,最后通过Relu激活函数层,输出channel为64;\n", "+ 主分支第二层网络的输入channel为64,首先通过一个$3\\times3$的卷积层,然后通过Batch Normalization层,输出channel为64。\n", "\n", "最后将主分支输出的特征矩阵与shortcuts输出的特征矩阵相加,通过Relu激活函数即为Building Block最后的输出。\n", "\n", "![building-block-5](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/tutorials/application/source_zh_cn/cv/images/resnet_5.png)\n", "\n", "主分支与shortcuts输出的特征矩阵相加时,需要保证主分支与shortcuts输出的特征矩阵shape相同。如果主分支与shortcuts输出的特征矩阵shape不相同,如输出channel是输入channel的一倍时,shortcuts上需要使用数量与输出channel相等,大小为$1\\times1$的卷积核进行卷积操作;若输出的图像较输入图像缩小一倍,则要设置shortcuts中卷积操作中的`stride`为2,主分支第一层卷积操作的`stride`也需设置为2。\n", "\n", "如下代码定义`ResidualBlockBase`类实现Building Block结构。" ] }, { "cell_type": "code", "execution_count": 4, "id": "c7ac0e2d", "metadata": {}, "outputs": [], "source": [ "from typing import Type, Union, List, Optional\n", "import mindspore.nn as nn\n", "from mindspore.common.initializer import Normal\n", "\n", "# 初始化卷积层与BatchNorm的参数\n", "weight_init = Normal(mean=0, sigma=0.02)\n", "gamma_init = Normal(mean=1, sigma=0.02)\n", "\n", "class ResidualBlockBase(nn.Cell):\n", " expansion: int = 1 # 最后一个卷积核数量与第一个卷积核数量相等\n", "\n", " def __init__(self, in_channel: int, out_channel: int,\n", " stride: int = 1, norm: Optional[nn.Cell] = None,\n", " down_sample: Optional[nn.Cell] = None) -> None:\n", " super(ResidualBlockBase, self).__init__()\n", " if not norm:\n", " self.norm = nn.BatchNorm2d(out_channel)\n", " else:\n", " self.norm = norm\n", "\n", " self.conv1 = nn.Conv2d(in_channel, out_channel,\n", " kernel_size=3, stride=stride,\n", " weight_init=weight_init)\n", " self.conv2 = nn.Conv2d(in_channel, out_channel,\n", " kernel_size=3, weight_init=weight_init)\n", " self.relu = nn.ReLU()\n", " self.down_sample = down_sample\n", "\n", " def construct(self, x):\n", " \"\"\"ResidualBlockBase construct.\"\"\"\n", " identity = x # shortcuts分支\n", "\n", " out = self.conv1(x) # 主分支第一层:3*3卷积层\n", " out = self.norm(out)\n", " out = self.relu(out)\n", " out = self.conv2(out) # 主分支第二层:3*3卷积层\n", " out = self.norm(out)\n", "\n", " if self.down_sample is not None:\n", " identity = self.down_sample(x)\n", " out += identity # 输出为主分支与shortcuts之和\n", " out = self.relu(out)\n", "\n", " return out" ] }, { "cell_type": "markdown", "id": "aaa15d3c", "metadata": {}, "source": [ "#### Bottleneck\n", "\n", "Bottleneck结构图如下图所示,在输入相同的情况下Bottleneck结构相对Building Block结构的参数数量更少,更适合层数较深的网络,ResNet50使用的残差结构就是Bottleneck。该结构的主分支有三层卷积结构,分别为$1\\times1$的卷积层、$3\\times3$卷积层和$1\\times1$的卷积层,其中$1\\times1$的卷积层分别起降维和升维的作用。\n", "\n", "+ 主分支第一层网络以输入channel为256为例,首先通过数量为64,大小为$1\\times1$的卷积核进行降维,然后通过Batch Normalization层,最后通过Relu激活函数层,其输出channel为64;\n", "+ 主分支第二层网络通过数量为64,大小为$3\\times3$的卷积核提取特征,然后通过Batch Normalization层,最后通过Relu激活函数层,其输出channel为64;\n", "+ 主分支第三层通过数量为256,大小$1\\times1$的卷积核进行升维,然后通过Batch Normalization层,其输出channel为256。\n", "\n", "最后将主分支输出的特征矩阵与shortcuts输出的特征矩阵相加,通过Relu激活函数即为Bottleneck最后的输出。\n", "\n", "![building-block-6](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/tutorials/application/source_zh_cn/cv/images/resnet_6.png)\n", "\n", "主分支与shortcuts输出的特征矩阵相加时,需要保证主分支与shortcuts输出的特征矩阵shape相同。如果主分支与shortcuts输出的特征矩阵shape不相同,如输出channel是输入channel的一倍时,shortcuts上需要使用数量与输出channel相等,大小为$1\\times1$的卷积核进行卷积操作;若输出的图像较输入图像缩小一倍,则要设置shortcuts中卷积操作中的`stride`为2,主分支第二层卷积操作的`stride`也需设置为2。\n", "\n", "如下代码定义`ResidualBlock`类实现Bottleneck结构。" ] }, { "cell_type": "code", "execution_count": 5, "id": "0d46f98e", "metadata": {}, "outputs": [], "source": [ "class ResidualBlock(nn.Cell):\n", " expansion = 4 # 最后一个卷积核的数量是第一个卷积核数量的4倍\n", "\n", " def __init__(self, in_channel: int, out_channel: int,\n", " stride: int = 1, down_sample: Optional[nn.Cell] = None) -> None:\n", " super(ResidualBlock, self).__init__()\n", "\n", " self.conv1 = nn.Conv2d(in_channel, out_channel,\n", " kernel_size=1, weight_init=weight_init)\n", " self.norm1 = nn.BatchNorm2d(out_channel)\n", " self.conv2 = nn.Conv2d(out_channel, out_channel,\n", " kernel_size=3, stride=stride,\n", " weight_init=weight_init)\n", " self.norm2 = nn.BatchNorm2d(out_channel)\n", " self.conv3 = nn.Conv2d(out_channel, out_channel * self.expansion,\n", " kernel_size=1, weight_init=weight_init)\n", " self.norm3 = nn.BatchNorm2d(out_channel * self.expansion)\n", "\n", " self.relu = nn.ReLU()\n", " self.down_sample = down_sample\n", "\n", " def construct(self, x):\n", "\n", " identity = x # shortscuts分支\n", "\n", " out = self.conv1(x) # 主分支第一层:1*1卷积层\n", " out = self.norm1(out)\n", " out = self.relu(out)\n", " out = self.conv2(out) # 主分支第二层:3*3卷积层\n", " out = self.norm2(out)\n", " out = self.relu(out)\n", " out = self.conv3(out) # 主分支第三层:1*1卷积层\n", " out = self.norm3(out)\n", "\n", " if self.down_sample is not None:\n", " identity = self.down_sample(x)\n", "\n", " out += identity # 输出为主分支与shortcuts之和\n", " out = self.relu(out)\n", "\n", " return out" ] }, { "cell_type": "markdown", "id": "d1d8dfc9", "metadata": {}, "source": [ "#### 构建ResNet50网络\n", "\n", "ResNet网络层结构如下图所示,以输入彩色图像$224\\times224$为例,首先通过数量64,卷积核大小为$7\\times7$,stride为2的卷积层conv1,该层输出图片大小为$112\\times112$,输出channel为64;然后通过一个$3\\times3$的最大下采样池化层,该层输出图片大小为$56\\times56$,输出channel为64;再堆叠4个残差网络块(conv2_x、conv3_x、conv4_x和conv5_x),此时输出图片大小为$7\\times7$,输出channel为2048;最后通过一个平均池化层、全连接层和softmax,得到分类概率。\n", "\n", "![resnet-layer](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/website-images/master/tutorials/application/source_zh_cn/cv/images/resnet_2.png)\n", "\n", "对于每个残差网络块,以ResNet50网络中的conv2_x为例,其由3个Bottleneck结构堆叠而成,每个Bottleneck输入的channel为64,输出channel为256。\n", "\n", "如下示例定义`make_layer`实现残差块的构建,其参数如下所示:\n", "\n", "+ `last_out_channel`:上一个残差网络输出的通道数。\n", "+ `block`:残差网络的类别,分别为`ResidualBlockBase`和`ResidualBlock`。\n", "+ `channel`:残差网络输入的通道数。\n", "+ `block_nums`:残差网络块堆叠的个数。\n", "+ `stride`:卷积移动的步幅。" ] }, { "cell_type": "code", "execution_count": 6, "id": "3dfa40a1", "metadata": {}, "outputs": [], "source": [ "def make_layer(last_out_channel, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n", " channel: int, block_nums: int, stride: int = 1):\n", " down_sample = None # shortcuts分支\n", "\n", " if stride != 1 or last_out_channel != channel * block.expansion:\n", "\n", " down_sample = nn.SequentialCell([\n", " nn.Conv2d(last_out_channel, channel * block.expansion,\n", " kernel_size=1, stride=stride, weight_init=weight_init),\n", " nn.BatchNorm2d(channel * block.expansion, gamma_init=gamma_init)\n", " ])\n", "\n", " layers = []\n", " layers.append(block(last_out_channel, channel, stride=stride, down_sample=down_sample))\n", "\n", " in_channel = channel * block.expansion\n", " # 堆叠残差网络\n", " for _ in range(1, block_nums):\n", "\n", " layers.append(block(in_channel, channel))\n", "\n", " return nn.SequentialCell(layers)" ] }, { "cell_type": "markdown", "id": "67dae353", "metadata": {}, "source": [ "ResNet50网络共有5个卷积结构,一个平均池化层,一个全连接层,以CIFAR-10数据集为例:\n", "\n", "+ **conv1**:输入图片大小为$32\\times32$,输入channel为3。首先经过一个卷积核数量为64,卷积核大小为$7\\times7$,stride为2的卷积层;然后通过一个Batch Normalization层;最后通过Reul激活函数。该层输出feature map大小为$16\\times16$,输出channel为64。\n", "+ **conv2_x**:输入feature map大小为$16\\times16$,输入channel为64。首先经过一个卷积核大小为$3\\times3$,stride为2的最大下采样池化操作;然后堆叠3个$[1\\times1,64;3\\times3,64;1\\times1,256]$结构的Bottleneck。该层输出feature map大小为$8\\times8$,输出channel为256。\n", "+ **conv3_x**:输入feature map大小为$8\\times8$,输入channel为256。该层堆叠4个[1×1,128;3×3,128;1×1,512]结构的Bottleneck。该层输出feature map大小为$4\\times4$,输出channel为512。\n", "+ **conv4_x**:输入feature map大小为$4\\times4$,输入channel为512。该层堆叠6个[1×1,256;3×3,256;1×1,1024]结构的Bottleneck。该层输出feature map大小为$2\\times2$,输出channel为1024。\n", "+ **conv5_x**:输入feature map大小为$2\\times2$,输入channel为1024。该层堆叠3个[1×1,512;3×3,512;1×1,2048]结构的Bottleneck。该层输出feature map大小为$1\\times1$,输出channel为2048。\n", "+ **average pool & fc**:输入channel为2048,输出channel为分类的类别数。\n", "\n", "如下示例代码实现ResNet50模型的构建,通过用调函数`resnet50`即可构建ResNet50模型,函数`resnet50`参数如下:\n", "\n", "+ `num_classes`:分类的类别数,默认类别数为1000。\n", "+ `pretrained`:下载对应的训练模型,并加载预训练模型中的参数到网络中。" ] }, { "cell_type": "code", "execution_count": 7, "id": "1ebef3d0", "metadata": {}, "outputs": [], "source": [ "from mindspore import load_checkpoint, load_param_into_net\n", "\n", "\n", "class ResNet(nn.Cell):\n", " def __init__(self, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n", " layer_nums: List[int], num_classes: int, input_channel: int) -> None:\n", " super(ResNet, self).__init__()\n", "\n", " self.relu = nn.ReLU()\n", " # 第一个卷积层,输入channel为3(彩色图像),输出channel为64\n", " self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, weight_init=weight_init)\n", " self.norm = nn.BatchNorm2d(64)\n", " # 最大池化层,缩小图片的尺寸\n", " self.max_pool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')\n", " # 各个残差网络结构块定义\n", " self.layer1 = make_layer(64, block, 64, layer_nums[0])\n", " self.layer2 = make_layer(64 * block.expansion, block, 128, layer_nums[1], stride=2)\n", " self.layer3 = make_layer(128 * block.expansion, block, 256, layer_nums[2], stride=2)\n", " self.layer4 = make_layer(256 * block.expansion, block, 512, layer_nums[3], stride=2)\n", " # 平均池化层\n", " self.avg_pool = nn.AvgPool2d()\n", " # flattern层\n", " self.flatten = nn.Flatten()\n", " # 全连接层\n", " self.fc = nn.Dense(in_channels=input_channel, out_channels=num_classes)\n", "\n", " def construct(self, x):\n", "\n", " x = self.conv1(x)\n", " x = self.norm(x)\n", " x = self.relu(x)\n", " x = self.max_pool(x)\n", "\n", " x = self.layer1(x)\n", " x = self.layer2(x)\n", " x = self.layer3(x)\n", " x = self.layer4(x)\n", "\n", " x = self.avg_pool(x)\n", " x = self.flatten(x)\n", " x = self.fc(x)\n", "\n", " return x" ] }, { "cell_type": "code", "execution_count": 8, "id": "d16e658e", "metadata": {}, "outputs": [], "source": [ "def _resnet(model_url: str, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n", " layers: List[int], num_classes: int, pretrained: bool, pretrained_ckpt: str,\n", " input_channel: int):\n", " model = ResNet(block, layers, num_classes, input_channel)\n", "\n", " if pretrained:\n", " # 加载预训练模型\n", " download(url=model_url, path=pretrained_ckpt, replace=True)\n", " param_dict = load_checkpoint(pretrained_ckpt)\n", " load_param_into_net(model, param_dict)\n", "\n", " return model\n", "\n", "\n", "def resnet50(num_classes: int = 1000, pretrained: bool = False):\n", " \"\"\"ResNet50模型\"\"\"\n", " resnet50_url = \"https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt\"\n", " resnet50_ckpt = \"./LoadPretrainedModel/resnet50_224_new.ckpt\"\n", " return _resnet(resnet50_url, ResidualBlock, [3, 4, 6, 3], num_classes,\n", " pretrained, resnet50_ckpt, 2048)" ] }, { "cell_type": "markdown", "id": "d40bd05a", "metadata": {}, "source": [ "## 模型训练与评估\n", "\n", "本节使用[ResNet50预训练模型](https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt)进行微调。调用`resnet50`构造ResNet50模型,并设置`pretrained`参数为True,将会自动下载ResNet50预训练模型,并加载预训练模型中的参数到网络中。然后定义优化器和损失函数,逐个epoch打印训练的损失值和评估精度,并保存评估精度最高的ckpt文件(resnet50-best.ckpt)到当前路径的./BestCheckPoint下。\n", "\n", "由于预训练模型全连接层(fc)的输出大小(对应参数`num_classes`)为1000, 为了成功加载预训练权重,我们将模型的全连接输出大小设置为默认的1000。CIFAR10数据集共有10个分类,在使用该数据集进行训练时,需要将加载好预训练权重的模型全连接层输出大小重置为10。\n", "\n", "> 此处我们展示了5个epochs的训练过程,如果想要达到理想的训练效果,建议训练80个epochs。" ] }, { "cell_type": "code", "execution_count": 9, "id": "9cf10c03", "metadata": {}, "outputs": [], "source": [ "# 定义ResNet50网络\n", "network = resnet50(pretrained=True)\n", "\n", "# 全连接层输入层的大小\n", "in_channel = network.fc.in_channels\n", "fc = nn.Dense(in_channels=in_channel, out_channels=10)\n", "# 重置全连接层\n", "network.fc = fc" ] }, { "cell_type": "code", "execution_count": 10, "id": "e1c632ff", "metadata": {}, "outputs": [], "source": [ "# 设置学习率\n", "num_epochs = 5\n", "lr = nn.cosine_decay_lr(min_lr=0.00001, max_lr=0.001, total_step=step_size_train * num_epochs,\n", " step_per_epoch=step_size_train, decay_epoch=num_epochs)\n", "# 定义优化器和损失函数\n", "opt = nn.Momentum(params=network.trainable_params(), learning_rate=lr, momentum=0.9)\n", "loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n", "\n", "\n", "def forward_fn(inputs, targets):\n", " logits = network(inputs)\n", " loss = loss_fn(logits, targets)\n", " return loss\n", "\n", "\n", "grad_fn = ms.value_and_grad(forward_fn, None, opt.parameters)\n", "\n", "\n", "def train_step(inputs, targets):\n", " loss, grads = grad_fn(inputs, targets)\n", " opt(grads)\n", " return loss" ] }, { "cell_type": "code", "execution_count": 11, "id": "b627e30c", "metadata": {}, "outputs": [], "source": [ "import os\n", "\n", "# 创建迭代器\n", "data_loader_train = dataset_train.create_tuple_iterator(num_epochs=num_epochs)\n", "data_loader_val = dataset_val.create_tuple_iterator(num_epochs=num_epochs)\n", "\n", "# 最佳模型存储路径\n", "best_acc = 0\n", "best_ckpt_dir = \"./BestCheckpoint\"\n", "best_ckpt_path = \"./BestCheckpoint/resnet50-best.ckpt\"\n", "\n", "if not os.path.exists(best_ckpt_dir):\n", " os.mkdir(best_ckpt_dir)" ] }, { "cell_type": "code", "execution_count": 12, "id": "8a5170df", "metadata": {}, "outputs": [], "source": [ "import mindspore.ops as ops\n", "\n", "\n", "def train(data_loader, epoch):\n", " \"\"\"模型训练\"\"\"\n", " losses = []\n", " network.set_train(True)\n", "\n", " for i, (images, labels) in enumerate(data_loader):\n", " loss = train_step(images, labels)\n", " if i % 100 == 0 or i == step_size_train - 1:\n", " print('Epoch: [%3d/%3d], Steps: [%3d/%3d], Train Loss: [%5.3f]' %\n", " (epoch + 1, num_epochs, i + 1, step_size_train, loss))\n", " losses.append(loss)\n", "\n", " return sum(losses) / len(losses)\n", "\n", "\n", "def evaluate(data_loader):\n", " \"\"\"模型验证\"\"\"\n", " network.set_train(False)\n", "\n", " correct_num = 0.0 # 预测正确个数\n", " total_num = 0.0 # 预测总数\n", "\n", " for images, labels in data_loader:\n", " logits = network(images)\n", " pred = logits.argmax(axis=1) # 预测结果\n", " correct = ops.equal(pred, labels).reshape((-1, ))\n", " correct_num += correct.sum().asnumpy()\n", " total_num += correct.shape[0]\n", "\n", " acc = correct_num / total_num # 准确率\n", "\n", " return acc" ] }, { "cell_type": "code", "execution_count": 13, "id": "562a04ca", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Start Training Loop ...\n", "Epoch: [ 1/ 5], Steps: [ 1/196], Train Loss: [2.389]\n", "Epoch: [ 1/ 5], Steps: [101/196], Train Loss: [1.467]\n", "Epoch: [ 1/ 5], Steps: [196/196], Train Loss: [1.093]\n", "--------------------------------------------------\n", "Epoch: [ 1/ 5], Average Train Loss: [1.641], Accuracy: [0.595]\n", "--------------------------------------------------\n", "Epoch: [ 2/ 5], Steps: [ 1/196], Train Loss: [1.253]\n", "Epoch: [ 2/ 5], Steps: [101/196], Train Loss: [0.974]\n", "Epoch: [ 2/ 5], Steps: [196/196], Train Loss: [0.832]\n", "--------------------------------------------------\n", "Epoch: [ 2/ 5], Average Train Loss: [1.019], Accuracy: [0.685]\n", "--------------------------------------------------\n", "Epoch: [ 3/ 5], Steps: [ 1/196], Train Loss: [0.917]\n", "Epoch: [ 3/ 5], Steps: [101/196], Train Loss: [0.879]\n", "Epoch: [ 3/ 5], Steps: [196/196], Train Loss: [0.743]\n", "--------------------------------------------------\n", "Epoch: [ 3/ 5], Average Train Loss: [0.852], Accuracy: [0.721]\n", "--------------------------------------------------\n", "Epoch: [ 4/ 5], Steps: [ 1/196], Train Loss: [0.911]\n", "Epoch: [ 4/ 5], Steps: [101/196], Train Loss: [0.703]\n", "Epoch: [ 4/ 5], Steps: [196/196], Train Loss: [0.768]\n", "--------------------------------------------------\n", "Epoch: [ 4/ 5], Average Train Loss: [0.777], Accuracy: [0.737]\n", "--------------------------------------------------\n", "Epoch: [ 5/ 5], Steps: [ 1/196], Train Loss: [0.793]\n", "Epoch: [ 5/ 5], Steps: [101/196], Train Loss: [0.809]\n", "Epoch: [ 5/ 5], Steps: [196/196], Train Loss: [0.734]\n", "--------------------------------------------------\n", "Epoch: [ 5/ 5], Average Train Loss: [0.745], Accuracy: [0.742]\n", "--------------------------------------------------\n", "================================================================================\n", "End of validation the best Accuracy is: 0.742, save the best ckpt file in ./BestCheckpoint/resnet50-best.ckpt\n" ] } ], "source": [ "# 开始循环训练\n", "print(\"Start Training Loop ...\")\n", "\n", "for epoch in range(num_epochs):\n", " curr_loss = train(data_loader_train, epoch)\n", " curr_acc = evaluate(data_loader_val)\n", "\n", " print(\"-\" * 50)\n", " print(\"Epoch: [%3d/%3d], Average Train Loss: [%5.3f], Accuracy: [%5.3f]\" % (\n", " epoch+1, num_epochs, curr_loss, curr_acc\n", " ))\n", " print(\"-\" * 50)\n", "\n", " # 保存当前预测准确率最高的模型\n", " if curr_acc > best_acc:\n", " best_acc = curr_acc\n", " ms.save_checkpoint(network, best_ckpt_path)\n", "\n", "print(\"=\" * 80)\n", "print(f\"End of validation the best Accuracy is: {best_acc: 5.3f}, \"\n", " f\"save the best ckpt file in {best_ckpt_path}\", flush=True)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "46e28f6f", "metadata": {}, "source": [ "## 可视化模型预测\n", "\n", "定义`visualize_model`函数,使用上述验证精度最高的模型对CIFAR-10测试数据集进行预测,并将预测结果可视化。若预测字体颜色为蓝色表示为预测正确,预测字体颜色为红色则表示预测错误。\n", "\n", "> 由上面的结果可知,5个epochs下模型在验证数据集的预测准确率在70%左右,即一般情况下,6张图片中会有2张预测失败。如果想要达到理想的训练效果,建议训练80个epochs。" ] }, { "cell_type": "code", "execution_count": null, "id": "6ba2fa94", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import matplotlib.pyplot as plt\n", "\n", "\n", "def visualize_model(best_ckpt_path, dataset_val):\n", " num_class = 10 # 对狼和狗图像进行二分类\n", " net = resnet50(num_class)\n", " # 加载模型参数\n", " param_dict = ms.load_checkpoint(best_ckpt_path)\n", " ms.load_param_into_net(net, param_dict)\n", " # 加载验证集的数据进行验证\n", " data = next(dataset_val.create_dict_iterator())\n", " images = data[\"image\"]\n", " labels = data[\"label\"]\n", " # 预测图像类别\n", " output = net(data['image'])\n", " pred = np.argmax(output.asnumpy(), axis=1)\n", "\n", " # 图像分类\n", " classes = []\n", "\n", " with open(data_dir + \"/batches.meta.txt\", \"r\") as f:\n", " for line in f:\n", " line = line.rstrip()\n", " if line:\n", " classes.append(line)\n", "\n", " # 显示图像及图像的预测值\n", " plt.figure()\n", " for i in range(6):\n", " plt.subplot(2, 3, i + 1)\n", " # 若预测正确,显示为蓝色;若预测错误,显示为红色\n", " color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'\n", " plt.title('predict:{}'.format(classes[pred[i]]), color=color)\n", " picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))\n", " mean = np.array([0.4914, 0.4822, 0.4465])\n", " std = np.array([0.2023, 0.1994, 0.2010])\n", " picture_show = std * picture_show + mean\n", " picture_show = np.clip(picture_show, 0, 1)\n", " plt.imshow(picture_show)\n", " plt.axis('off')\n", "\n", " plt.show()\n", "\n", "\n", "# 使用测试数据集进行验证\n", "visualize_model(best_ckpt_path=best_ckpt_path, dataset_val=dataset_val)" ] } ], "metadata": { "kernelspec": { "display_name": "MindSpore", "language": "python", "name": "mindspore" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 5 }