{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "# Copyright 2021 Huawei Technologies Co., Ltd\n", "#\n", "# Licensed under the Apache License, Version 2.0 (the \"License\");\n", "# you may not use this file except in compliance with the License.\n", "# You may obtain a copy of the License at\n", "#\n", "# http://www.apache.org/licenses/LICENSE-2.0\n", "#\n", "# Unless required by applicable law or agreed to in writing, software\n", "# distributed under the License is distributed on an \"AS IS\" BASIS,\n", "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n", "# See the License for the specific language governing permissions and\n", "# limitations under the License.\n", "# ============================================================================\n", "\"\"\"\n", "import mindspore\n", "ResNet code gently borrowed from\n", "https://github.com/pytorch/vision/blob/master/torchvision/models/resnet.py\n", "\"\"\"\n", "import mindspore.nn as nn\n", "import mindspore.ops.operations as P\n", "from mindspore.common import dtype as mstype\n", "\n", "\n", "\n", "conv_weight_init = 'HeUniform'\n", "\n", "\n", "class GroupConv(nn.Cell):\n", " \"\"\"\n", " group convolution operation.\n", "\n", " Args:\n", " in_channels (int): Input channels of feature map.\n", " out_channels (int): Output channels of feature map.\n", " kernel_size (int): Size of convolution kernel.\n", " stride (int): Stride size for the group convolution layer.\n", "\n", " Returns:\n", " tensor, output tensor.\n", " \"\"\"\n", " def __init__(self, in_channels, out_channels, kernel_size,\n", " stride, pad_mode=\"pad\", padding=0, group=1, has_bias=False):\n", " super(GroupConv, self).__init__()\n", " assert in_channels % group == 0 and out_channels % group == 0\n", " self.group = group\n", " self.convs = nn.CellList()\n", " self.op_split = P.Split(axis=1, output_num=self.group)\n", " self.op_concat = P.Concat(axis=1)\n", " self.cast = P.Cast()\n", " for _ in range(group):\n", " self.convs.append(nn.Conv2d(in_channels//group, out_channels//group,\n", " kernel_size=kernel_size, stride=stride, has_bias=has_bias,\n", " padding=padding, pad_mode=pad_mode, group=1, weight_init=conv_weight_init))\n", "\n", " def construct(self, x):\n", " features = self.op_split(x)\n", " outputs = ()\n", " for i in range(self.group):\n", " outputs = outputs + (self.convs[i](self.cast(features[i], mstype.float32)),)\n", " out = self.op_concat(outputs)\n", " return out\n", "\n", "\n", "class SEModule(nn.Cell):\n", " \"\"\"\n", " SEModule\n", " \"\"\"\n", " def __init__(self, channels, reduction):\n", " super(SEModule, self).__init__()\n", " self.avg_pool = P.ReduceMean(keep_dims=True)\n", " self.fc1 = nn.Conv2d(in_channels=channels, out_channels=channels // reduction, kernel_size=1,\n", " pad_mode='pad', padding=0, has_bias=True, weight_init=conv_weight_init)\n", " self.relu = nn.ReLU()\n", " self.fc2 = nn.Conv2d(in_channels=channels // reduction, out_channels=channels, kernel_size=1,\n", " pad_mode='pad', padding=0, has_bias=False, weight_init=conv_weight_init)\n", " self.sigmoid = nn.Sigmoid()\n", "\n", " def construct(self, x):\n", " \"\"\"\n", " construct\n", " \"\"\"\n", " module_input = x\n", " x = self.avg_pool(x, (2, 3))\n", " x = self.fc1(x)\n", " x = self.relu(x)\n", " x = self.fc2(x)\n", " x = self.sigmoid(x)\n", " return module_input * x\n", "\n", "\n", "class Bottleneck(nn.Cell):\n", " \"\"\"\n", " Base class for bottlenecks that implements `forward()` method.\n", " \"\"\"\n", " def construct(self, x):\n", " \"\"\"\n", " construct\n", " \"\"\"\n", " residual = x\n", "\n", " out = self.conv1(x)\n", " out = self.bn1(out)\n", " out = self.relu(out)\n", "\n", " out = self.conv2(out)\n", " out = self.bn2(out)\n", " out = self.relu(out)\n", "\n", " out = self.conv3(out)\n", " out = self.bn3(out)\n", "\n", " if self.downsample is not None:\n", " residual = self.downsample(x)\n", "\n", " out = self.se_module(out) + residual\n", " out = self.relu(out)\n", "\n", " return out\n", "\n", "\n", "class SEBottleneck(Bottleneck):\n", " \"\"\"\n", " Bottleneck for SENet154.\n", " \"\"\"\n", " expansion = 4\n", "\n", " def __init__(self, inplanes, planes, group, reduction, stride=1,\n", " downsample=None):\n", " super(SEBottleneck, self).__init__()\n", " self.conv1 = nn.Conv2d(inplanes, planes * 2, kernel_size=1, has_bias=False, weight_init=conv_weight_init)\n", " self.bn1 = nn.BatchNorm2d(planes * 2)\n", " self.conv2 = GroupConv(planes * 2, planes * 4, kernel_size=3, pad_mode='pad',\n", " stride=stride, padding=1, group=group,\n", " has_bias=False)\n", " self.bn2 = nn.BatchNorm2d(planes * 4)\n", " self.conv3 = nn.Conv2d(planes * 4, planes * 4, kernel_size=1,\n", " has_bias=False, weight_init=conv_weight_init)\n", " self.bn3 = nn.BatchNorm2d(planes * 4)\n", " self.relu = nn.ReLU()\n", " self.se_module = SEModule(planes * 4, reduction=reduction)\n", " self.downsample = downsample\n", " self.stride = stride\n", "\n", "\n", "class SEResNetBottleneck(Bottleneck):\n", " \"\"\"\n", " ResNet bottleneck with a Squeeze-and-Excitation module. It follows Caffe\n", " implementation and uses `stride=stride` in `conv1` and not in `conv2`\n", " (the latter is used in the torchvision implementation of ResNet).\n", " \"\"\"\n", " expansion = 4\n", "\n", " def __init__(self, inplanes, planes, group, reduction, stride=1,\n", " downsample=None):\n", " super(SEResNetBottleneck, self).__init__()\n", " self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, has_bias=False,\n", " stride=stride, weight_init=conv_weight_init)\n", " self.bn1 = nn.BatchNorm2d(planes)\n", " self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, pad_mode='pad', padding=1,\n", " group=group, has_bias=False, weight_init=conv_weight_init)\n", " self.bn2 = nn.BatchNorm2d(planes)\n", " self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, has_bias=False, weight_init=conv_weight_init)\n", " self.bn3 = nn.BatchNorm2d(planes * 4)\n", " self.relu = nn.ReLU()\n", " self.se_module = SEModule(planes * 4, reduction=reduction)\n", " self.downsample = downsample\n", " self.stride = stride\n", "\n", "\n", "class SEResNeXtBottleneck(Bottleneck):\n", " \"\"\"\n", " ResNeXt bottleneck type C with a Squeeze-and-Excitation module.\n", " \"\"\"\n", " expansion = 4\n", "\n", " def __init__(self, inplanes, planes, group, reduction, stride=1,\n", " downsample=None, base_width=4):\n", " super(SEResNeXtBottleneck, self).__init__()\n", " width = int(planes * (base_width / 64.0)) * group\n", " self.conv1 = nn.Conv2d(inplanes, width, kernel_size=1, has_bias=False,\n", " stride=1, weight_init=conv_weight_init)\n", " self.bn1 = nn.BatchNorm2d(width)\n", " self.conv2 = GroupConv(width, width, kernel_size=3, stride=stride, pad_mode='pad',\n", " padding=1, group=group, has_bias=False)\n", " self.bn2 = nn.BatchNorm2d(width)\n", " self.conv3 = nn.Conv2d(width, planes * 4, kernel_size=1, has_bias=False, weight_init=conv_weight_init)\n", " self.bn3 = nn.BatchNorm2d(planes * 4)\n", " self.relu = nn.ReLU()\n", " self.se_module = SEModule(planes * 4, reduction=reduction)\n", " self.downsample = downsample\n", " self.stride = stride\n", "\n", "\n", "class SENet(nn.Cell):\n", " \"\"\"\n", " SENet.\n", " \"\"\"\n", " def __init__(self, block, layers, group, reduction, dropout_p=0.2,\n", " inplanes=128, input_3x3=True, downsample_kernel_size=3,\n", " downsample_padding=1, num_classes=1000):\n", " \"\"\"\n", " Parameters\n", " ----------\n", " block (nn.Module): Bottleneck class.\n", " - For SENet154: SEBottleneck\n", " - For SE-ResNet models: SEResNetBottleneck\n", " - For SE-ResNeXt models: SEResNeXtBottleneck\n", " layers (list of ints): Number of residual blocks for 4 layers of the\n", " network (layer1...layer4).\n", " group (int): Number of group for the 3x3 convolution in each\n", " bottleneck block.\n", " - For SENet154: 64\n", " - For SE-ResNet models: 1\n", " - For SE-ResNeXt models: 32\n", " reduction (int): Reduction ratio for Squeeze-and-Excitation modules.\n", " - For all models: 16\n", " dropout_p (float or None): Drop probability for the Dropout layer.\n", " If `None` the Dropout layer is not used.\n", " - For SENet154: 0.2\n", " - For SE-ResNet models: None\n", " - For SE-ResNeXt models: None\n", " inplanes (int): Number of input channels for layer1.\n", " - For SENet154: 128\n", " - For SE-ResNet models: 64\n", " - For SE-ResNeXt models: 64\n", " input_3x3 (bool): If `True`, use three 3x3 convolutions instead of\n", " a single 7x7 convolution in layer0.\n", " - For SENet154: True\n", " - For SE-ResNet models: False\n", " - For SE-ResNeXt models: False\n", " downsample_kernel_size (int): Kernel size for downsampling convolutions\n", " in layer2, layer3 and layer4.\n", " - For SENet154: 3\n", " - For SE-ResNet models: 1\n", " - For SE-ResNeXt models: 1\n", " downsample_padding (int): Padding for downsampling convolutions in\n", " layer2, layer3 and layer4.\n", " - For SENet154: 1\n", " - For SE-ResNet models: 0\n", " - For SE-ResNeXt models: 0\n", " num_classes (int): Number of outputs in `last_linear` layer.\n", " - For all models: 1000\n", " \"\"\"\n", " super(SENet, self).__init__()\n", " self.inplanes = inplanes\n", " if input_3x3:\n", " layer0_modules = [\n", " nn.Conv2d(in_channels=3, out_channels=64, kernel_size=3, stride=2, pad_mode='pad',\n", " padding=1, has_bias=False, weight_init=conv_weight_init),\n", " nn.BatchNorm2d(num_features=64, momentum=0.9),\n", " nn.ReLU(),\n", " nn.Conv2d(in_channels=64, out_channels=64, kernel_size=3, stride=1, pad_mode='pad',\n", " padding=1, has_bias=False, weight_init=conv_weight_init),\n", " nn.BatchNorm2d(num_features=64, momentum=0.9),\n", " nn.ReLU(),\n", " nn.Conv2d(in_channels=64, out_channels=inplanes, kernel_size=3, stride=1,\n", " pad_mode='pad', padding=1, has_bias=False, weight_init=conv_weight_init),\n", " nn.BatchNorm2d(num_features=inplanes, momentum=0.9),\n", " nn.ReLU(),\n", " ]\n", " else:\n", " layer0_modules = [\n", " nn.Conv2d(in_channels=3, out_channels=inplanes, kernel_size=7, stride=2, pad_mode='pad',\n", " padding=3, has_bias=False, weight_init=conv_weight_init),\n", " nn.BatchNorm2d(num_features=inplanes, momentum=0.9),\n", " nn.ReLU(),\n", " ]\n", " layer0_modules.append(nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same'))\n", " self.layer0 = nn.SequentialCell(layer0_modules)\n", " self.layer1 = self._make_layer(\n", " block,\n", " planes=64,\n", " blocks=layers[0],\n", " group=group,\n", " reduction=reduction,\n", " downsample_kernel_size=1,\n", " downsample_padding=0\n", " )\n", " self.layer2 = self._make_layer(\n", " block,\n", " planes=128,\n", " blocks=layers[1],\n", " stride=2,\n", " group=group,\n", " reduction=reduction,\n", " downsample_kernel_size=downsample_kernel_size,\n", " downsample_padding=downsample_padding\n", " )\n", " self.layer3 = self._make_layer(\n", " block,\n", " planes=256,\n", " blocks=layers[2],\n", " stride=2,\n", " group=group,\n", " reduction=reduction,\n", " downsample_kernel_size=downsample_kernel_size,\n", " downsample_padding=downsample_padding\n", " )\n", " self.layer4 = self._make_layer(\n", " block,\n", " planes=512,\n", " blocks=layers[3],\n", " stride=2,\n", " group=group,\n", " reduction=reduction,\n", " downsample_kernel_size=downsample_kernel_size,\n", " downsample_padding=downsample_padding\n", " )\n", " self.avg_pool = nn.AvgPool2d(kernel_size=7, stride=1, pad_mode='valid')\n", " self.dropout = nn.Dropout(keep_prob=1.0 - dropout_p) if dropout_p is not None else None\n", " self.last_linear = nn.Dense(in_channels=512 * block.expansion, out_channels=num_classes, has_bias=False)\n", "\n", " def _make_layer(self, block, planes, blocks, group, reduction, stride=1,\n", " downsample_kernel_size=1, downsample_padding=0):\n", " \"\"\"\n", " _make_layer\n", " \"\"\"\n", " downsample = None\n", " if stride != 1 or self.inplanes != planes * block.expansion:\n", " downsample = nn.SequentialCell([\n", " nn.Conv2d(in_channels=self.inplanes, out_channels=planes * block.expansion,\n", " kernel_size=downsample_kernel_size, stride=stride, pad_mode='pad',\n", " padding=downsample_padding, has_bias=False, weight_init=conv_weight_init),\n", " nn.BatchNorm2d(num_features=planes * block.expansion, momentum=0.9),\n", " ])\n", "\n", " layers = []\n", " layers.append(block(self.inplanes, planes, group, reduction, stride,\n", " downsample))\n", " self.inplanes = planes * block.expansion\n", " for _ in range(1, blocks):\n", " layers.append(block(self.inplanes, planes, group, reduction))\n", "\n", " return nn.SequentialCell([*layers])\n", "\n", " def features(self, x):\n", " \"\"\"\n", " features\n", " \"\"\"\n", " x = self.layer0(x)\n", " x = self.layer1(x)\n", " x = self.layer2(x)\n", " x = self.layer3(x)\n", " x = self.layer4(x)\n", " return x\n", "\n", " def logits(self, x):\n", " \"\"\"\n", " logits\n", " \"\"\"\n", " x = self.avg_pool(x)\n", " if self.dropout is not None:\n", " x = self.dropout(x)\n", " x = P.Reshape()(x, (P.Shape()(x)[0], -1,))\n", " x = self.last_linear(x)\n", " return x\n", "\n", " def construct(self, x):\n", " \"\"\"\n", " construct\n", " \"\"\"\n", " x = self.features(x)\n", " x = self.logits(x)\n", " return x\n", "\n", "\n", "def senet154(num_classes=1000):\n", " model = SENet(SEBottleneck, [3, 8, 36, 3], group=64, reduction=16,\n", " dropout_p=0.2, num_classes=num_classes)\n", " return model\n", "\n", "\n", "def se_resnet50(num_classes=1000):\n", " model = SENet(SEResNetBottleneck, [3, 4, 6, 3], group=1, reduction=16,\n", " dropout_p=None, inplanes=64, input_3x3=False,\n", " downsample_kernel_size=1, downsample_padding=0,\n", " num_classes=num_classes)\n", " return model\n", "\n", "\n", "def se_resnet101(num_classes=1000):\n", " model = SENet(SEResNetBottleneck, [3, 4, 23, 3], group=1, reduction=16,\n", " dropout_p=None, inplanes=64, input_3x3=False,\n", " downsample_kernel_size=1, downsample_padding=0,\n", " num_classes=num_classes)\n", " return model\n", "\n", "\n", "def se_resnet152(num_classes=1000):\n", " model = SENet(SEResNetBottleneck, [3, 8, 36, 3], group=1, reduction=16,\n", " dropout_p=None, inplanes=64, input_3x3=False,\n", " downsample_kernel_size=1, downsample_padding=0,\n", " num_classes=num_classes)\n", " return model\n", "\n", "\n", "def se_resnext50_32x4d(num_classes=1000):\n", " model = SENet(SEResNeXtBottleneck, [3, 4, 6, 3], group=32, reduction=16,\n", " dropout_p=None, inplanes=64, input_3x3=False,\n", " downsample_kernel_size=1, downsample_padding=0,\n", " num_classes=num_classes)\n", " return model\n", "\n", "\n", "def se_resnext101_32x4d(num_classes=1000):\n", " model = SENet(SEResNeXtBottleneck, [3, 4, 23, 3], group=32, reduction=16,\n", " dropout_p=None, inplanes=64, input_3x3=False,\n", " downsample_kernel_size=1, downsample_padding=0,\n", " num_classes=num_classes)\n", " return model\n", "\n", "\n", " \n", "se_resnext = se_resnext50_32x4d(num_classes=5)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "import os\n", "import shutil\n", "\n", "# 训练集路径\n", "train_path = '/hy-tmp/Enderfga/plant_dataset/train'\n", "# 验证集路径\n", "val_path = '/hy-tmp/Enderfga/plant_dataset/val'\n", "# 测试集路径\n", "test_path = '/hy-tmp/Enderfga/plant_dataset/test'\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "\n", "# 读取train,val路径下的csv并合并,把val的图片移到train中\n", "train_csv = pd.read_csv(train_path + '/train_label.csv')\n", "val_csv = pd.read_csv(val_path + '/val_label.csv')\n", "train_csv = pd.concat([train_csv, val_csv], axis=0)\n", "train_csv.to_csv(train_path + '/train_label.csv', index=False)\n", "images = os.listdir(val_path + '/images')\n", "for image in images:\n", " shutil.move(val_path + '/images/' + image, train_path + '/images/' + image)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "train = pd.read_csv(test_path + '/test_label.csv')\n", "a = train['labels'].unique()\n", "for i in range(len(a)):\n", " a[i] = a[i].split()\n", "label_unique = []\n", "for i in range(len(a)):\n", " for j in range(len(a[i])):\n", " if a[i][j] not in label_unique:\n", " label_unique.append(a[i][j])\n", " else: \n", " pass\n", "print(a)\n", "print(label_unique)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "train[label_unique] = 0\n", "train[\"labels\"] = train[\"labels\"].apply(lambda x:x.split(\" \")) \n", "train" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "for i in range(len(train)):\n", " for item in label_unique:\n", " if item in train.iloc[i,1]:\n", " train.loc[i,item] = 1\n", " else: \n", " pass\n", "train" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "阈值大于0.55则认为有对应的疾病,对所有疾病都呈阴性的图像被认为是healthy" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 删除healthy列值为1的行\n", "train = train[train['healthy'] != 1]\n", "# 删除train中的labels列和healthy列\n", "train = train.drop(['labels'], axis=1)\n", "train = train.drop(['healthy'], axis=1)\n", "train" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# test与train的label必须保持一致,train的顺序为healthy,scab,frog_eye_leaf_spot,complex,powdery_mildew,rust\n", "# 调整test的顺序\n", "test = train[['images','scab','frog_eye_leaf_spot','complex','powdery_mildew','rust']]\n", "#test.to_csv(test_path + '/test_label_pre.csv', index=False)\n", "test" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#train.to_csv(train_path + '/train_label_pre.csv', index=False)\n", "train = pd.read_csv(train_path + '/train_label_pre.csv')" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from PIL import Image\n", "class KF_Dataset():\n", "\n", " def __init__(self, csv,spilt='train'):\n", " super(KF_Dataset, self).__init__()\n", " self.train = csv\n", " self.spilt = spilt\n", " self.imgs = self.train['images'].values\n", " self.labels = self.train.drop(['images'], axis=1).values\n", "\n", "\n", " def __getitem__(self, index):\n", " if self.spilt == 'train':\n", " img = Image.open('/hy-tmp/Enderfga/plant_dataset/train/images/'+self.imgs[index]).convert('RGB')\n", " else:\n", " img = Image.open('/hy-tmp/Enderfga/plant_dataset/test/images/'+self.imgs[index]).convert('RGB')\n", " return img, self.labels[index]\n", "\n", " def __len__(self):\n", " return len(self.imgs)\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 根据fold划分数据集,返回五份训练集和验证集\n", "import pandas as pd\n", "train_path = '/hy-tmp/Enderfga/plant_dataset/train'\n", "train = pd.read_csv(train_path + '/train_label_pre.csv')\n", "from sklearn.model_selection import KFold\n", "kf = KFold(n_splits=5, shuffle=True, random_state=2022)\n", "train_index = []\n", "val_index = []\n", "for train_index_, val_index_ in kf.split(train):\n", " train_index.append(train_index_)\n", " val_index.append(val_index_)\n", "train_set = []\n", "val_set = []\n", "for i in range(5):\n", " train_set.append(KF_Dataset(train.iloc[train_index[i]],spilt='train'))\n", " val_set.append(KF_Dataset(train.iloc[val_index[i]],spilt='train'))\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import mindspore.dataset as de\n", "from mindspore import dtype as mstype\n", "import mindspore.dataset.vision as C\n", "import mindspore.dataset.transforms as C2\n", "from mindspore.dataset.vision import ImageBatchFormat\n", "from mindspore.dataset.vision import AutoAugmentPolicy, Inter\n", "\n", "def create_dataset(dataset, repeat_num=1, batch_size=32, target='train', image_size=224):\n", " # 定义数据增强\n", " mean = [0.485 * 255, 0.456 * 255, 0.406 * 255]\n", " std = [0.229 * 255, 0.224 * 255, 0.225 * 255]\n", " scale = 32\n", " type_op = C2.TypeCast(mstype.float32)\n", " if target == \"train\":\n", " # Define map operations for training dataset\n", " trans = [\n", " C.Resize(size=[image_size, image_size]),\n", " C.RandomHorizontalFlip(prob=0.5),\n", " C.RandomRotation(degrees=15),\n", " C.RandomColorAdjust(brightness=0.4, contrast=0.4, saturation=0.4),\n", " C.AutoAugment(policy=AutoAugmentPolicy.IMAGENET,interpolation=Inter.NEAREST,fill_value=0),\n", " C.Normalize(mean=mean, std=std),\n", " C.HWC2CHW(),\n", " type_op\n", " ]\n", " else:\n", " # Define map operations for inference dataset\n", " trans = [\n", " C.Resize(size=[image_size + scale, image_size + scale]),\n", " C.CenterCrop(image_size),\n", " C.Normalize(mean=mean, std=std),\n", " C.HWC2CHW(),\n", " type_op\n", " ]\n", " cutmix_batch_op = C.CutMixBatch(ImageBatchFormat.NCHW, 1.0, 0.5)\n", "\n", " dataset = de.GeneratorDataset(dataset, [\"image\", \"label\"])\n", " dataset = dataset.map(operations=trans, input_columns=\"image\", num_parallel_workers=8)\n", " \n", " # 设置batch_size的大小,若最后一次抓取的样本数小于batch_size,则丢弃\n", " dataset = dataset.batch(batch_size, drop_remainder=True)\n", " if target == \"train\":\n", " dataset = dataset.map(operations=cutmix_batch_op, input_columns=[\"image\", \"label\"], num_parallel_workers=8)\n", " dataset = dataset.map(operations=type_op, input_columns=\"label\", num_parallel_workers=8)\n", " # 设置数据集重复次数\n", " dataset = dataset.repeat(repeat_num)\n", " return dataset" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "from mindspore.train import Model\n", "from mindspore import context\n", "context.set_context(mode=context.GRAPH_MODE, device_target=\"GPU\")\n", "from mindvision.engine.callback import ValAccMonitor\n", "import mindspore as ms\n", "from mindspore import ops\n", "import mindspore.nn as nn\n", "\n", "net_loss = nn.MultiClassDiceLoss(weights=None, ignore_indiex=None, activation=\"softmax\")\n", "\n", "\n", "#net_opt = nn.Adam(se_resnext.trainable_params(), learning_rate=0.001, beta1=0.9, beta2=0.999, eps=1e-08, loss_scale=1.0)\n", "\n", "\n", "\n", "\n", "def train_loop(model, dataset, loss_fn, optimizer):\n", " # Define forward function\n", " def forward_fn(data, label):\n", " logits = model(data)\n", " loss = loss_fn(logits, label)\n", " return loss, logits\n", "\n", " # Get gradient function\n", " grad_fn = ops.value_and_grad(forward_fn, None, optimizer.parameters, has_aux=True)\n", "\n", " # Define function of one-step training\n", " def train_step(data, label):\n", " (loss, _), grads = grad_fn(data, label)\n", " loss = ops.depend(loss, optimizer(grads))\n", " return loss\n", "\n", " size = dataset.get_dataset_size()\n", " model.set_train()\n", " for batch, (data, label) in enumerate(dataset.create_tuple_iterator()):\n", " loss = train_step(data, label)\n", "\n", " if batch % 100 == 0:\n", " loss, current = loss.asnumpy(), batch\n", " print(f\"loss: {loss:>7f}\\n\")\n", "\n", "\n", "def test_loop(model, dataset, loss_fn,name,best_acc=0):\n", " num_batches = dataset.get_dataset_size()\n", " model.set_train(False)\n", " total, test_loss, correct = 0, 0, 0\n", " for data, label in dataset.create_tuple_iterator():\n", " pred = model(data)\n", " total += len(data)\n", " test_loss += loss_fn(pred, label).asnumpy()\n", " pred_probab = nn.Softmax(axis=1)(pred)\n", " # 如果预测概率大于0.55,则预测设为1,否则为0\n", " pred = pred_probab > 0.55\n", " # 计算pred和label中有多少行相同\n", " for i in range(len(pred)):\n", " if (pred[i] == label[i]).all():\n", " correct += 1\n", " test_loss /= num_batches\n", " correct /= total\n", " if correct > best_acc:\n", " best_acc = correct\n", " ms.save_checkpoint(model, name+\"best.ckpt\")\n", " print(f\"Test: \\n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \\n\")\n", " return best_acc" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "se_resnext = se_resnext50_32x4d(num_classes=5)\n", "dataset_train = create_dataset(train_set[0], batch_size=128, target='train', image_size=224)\n", "dataset_val = create_dataset(val_set[0], batch_size=128, target='val', image_size=224)\n", "net_opt = nn.Adam(se_resnext.trainable_params(), learning_rate=0.001, beta1=0.9, beta2=0.999, eps=1e-08, loss_scale=1.0)\n", "epochs = 50\n", "for t in range(epochs):\n", " print(f\"Epoch {t+1}\\n-------------------------------\")\n", " train_loop(se_resnext, dataset_train, net_loss, net_opt)\n", " test_loop(se_resnext, dataset_val, net_loss,'fold1_')\n", "print(\"Done!\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "se_resnext = se_resnext50_32x4d(num_classes=5)\n", "dataset_train = create_dataset(train_set[1], batch_size=128, target='train', image_size=224)\n", "dataset_val = create_dataset(val_set[1], batch_size=128, target='val', image_size=224)\n", "net_opt = nn.Adam(se_resnext.trainable_params(), learning_rate=0.001, beta1=0.9, beta2=0.999, eps=1e-08, loss_scale=1.0)\n", "epochs = 50\n", "for t in range(epochs):\n", " print(f\"Epoch {t+1}\\n-------------------------------\")\n", " train_loop(se_resnext, dataset_train, net_loss, net_opt)\n", " test_loop(se_resnext, dataset_val, net_loss,'fold2_')\n", "print(\"Done!\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "dataset_train = create_dataset(train_set[2], batch_size=128, target='train', image_size=224)\n", "dataset_val = create_dataset(val_set[2], batch_size=128, target='val', image_size=224)\n", "net_opt = nn.Adam(se_resnext.trainable_params(), learning_rate=0.001, beta1=0.9, beta2=0.999, eps=1e-08, loss_scale=1.0)\n", "epochs = 50\n", "for t in range(epochs):\n", " print(f\"Epoch {t+1}\\n-------------------------------\")\n", " train_loop(se_resnext, dataset_train, net_loss, net_opt)\n", " test_loop(se_resnext, dataset_val, net_loss,'fold3_')\n", "print(\"Done!\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "se_resnext = se_resnext50_32x4d(num_classes=5)\n", "dataset_train = create_dataset(train_set[3], batch_size=128, target='train', image_size=224)\n", "dataset_val = create_dataset(val_set[3], batch_size=128, target='val', image_size=224)\n", "net_opt = nn.Adam(se_resnext.trainable_params(), learning_rate=0.001, beta1=0.9, beta2=0.999, eps=1e-08, loss_scale=1.0)\n", "epochs = 50\n", "for t in range(epochs):\n", " print(f\"Epoch {t+1}\\n-------------------------------\")\n", " train_loop(se_resnext, dataset_train, net_loss, net_opt)\n", " test_loop(se_resnext, dataset_val, net_loss,'fold4_')\n", "print(\"Done!\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "se_resnext = se_resnext50_32x4d(num_classes=5)\n", "dataset_train = create_dataset(train_set[4], batch_size=128, target='train', image_size=224)\n", "dataset_val = create_dataset(val_set[4], batch_size=128, target='val', image_size=224)\n", "net_opt = nn.Adam(se_resnext.trainable_params(), learning_rate=0.001, beta1=0.9, beta2=0.999, eps=1e-08, loss_scale=1.0)\n", "epochs = 50\n", "for t in range(epochs):\n", " print(f\"Epoch {t+1}\\n-------------------------------\")\n", " train_loop(se_resnext, dataset_train, net_loss, net_opt)\n", " test_loop(se_resnext, dataset_val, net_loss,'fold5_')\n", "print(\"Done!\")" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "load success\n" ] } ], "source": [ "import mindspore as ms\n", "se_resnext = se_resnext50_32x4d(num_classes=5)\n", "param_dict = ms.load_checkpoint(\"best.ckpt\")\n", "param_not_load = ms.load_param_into_net(se_resnext, param_dict)\n", "if param_not_load==[]:\n", " print(\"load success\")\n" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Test: \n", " Accuracy: 90.5%, Avg loss: 0.082346 \n", "\n" ] }, { "data": { "text/plain": [ "0.905" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "test = pd.read_csv('/hy-tmp/Enderfga/plant_dataset/test/test_label_pre.csv')\n", "testset = create_dataset(KF_Dataset(test,spilt='test'), batch_size=600, target='test', image_size=224)\n", "test_loop(se_resnext, testset, net_loss,'test')" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import pandas as pd\n", "train = pd.read_csv('/hy-tmp/Enderfga/plant_dataset/train/train_label_pre.csv')\n", "dataset_train = create_dataset(KF_Dataset(train,spilt='train'), batch_size=128, target='train', image_size=224)\n", "dataset_val = create_dataset(KF_Dataset(train,spilt='train'), batch_size=120, target='val', image_size=224)\n", "net_opt = nn.Adam(se_resnext.trainable_params(), learning_rate=0.001, beta1=0.9, beta2=0.999, eps=1e-08, loss_scale=1.0)\n", "optim = nn.Adam(params=se_resnext.trainable_params())\n", "\n", "#2) Use parameter groups and set different values\n", "conv_params = list(filter(lambda x: 'conv' in x.name, se_resnext.trainable_params()))\n", "no_conv_params = list(filter(lambda x: 'conv' not in x.name, se_resnext.trainable_params()))\n", "group_params = [{'params': conv_params, 'weight_decay': 0.01, 'grad_centralization':True},\n", " {'params': no_conv_params, 'lr': 0.01},\n", " {'order_params': se_resnext.trainable_params()}]\n", "optim = nn.Adam(group_params, learning_rate=0.1, weight_decay=0.0)\n", "epochs = 100\n", "correct = 0\n", "for t in range(epochs):\n", " print(f\"Epoch {t+1}\\n-------------------------------\")\n", " train_loop(se_resnext, dataset_train, net_loss, net_opt)\n", " tmp = test_loop(se_resnext, dataset_val, net_loss,'fold5_')\n", " if tmp>correct:\n", " correct = tmp\n", " ms.save_checkpoint(se_resnext, 'best.ckpt')\n", "print(\"Done!\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import mindspore as ms\n", "import pandas as pd\n", "import numpy as np\n", "model_list = ['fold1_best.ckpt','fold2_best.ckpt','fold3_best.ckpt','fold4_best.ckpt','fold5_best.ckpt']\n", "test = pd.read_csv('/hy-tmp/Enderfga/plant_dataset/test/test_label_pre.csv')\n", "testset = create_dataset(KF_Dataset(test,spilt='test'), batch_size=600, target='test', image_size=224)\n", "def load_model(model_name):\n", " se_resnext = se_resnext50_32x4d(num_classes=5)\n", " param_dict = ms.load_checkpoint(model_name)\n", " param_not_load = ms.load_param_into_net(se_resnext, param_dict)\n", " if param_not_load==[]:\n", " print(\"load success\")\n", " return se_resnext\n", "def acc(model_list, dataset):\n", " num_batches = dataset.get_dataset_size()\n", " num_model = len(model_list)\n", " #使用五个模型预测,然后取平均\n", " for i in range(num_model):\n", " model = load_model(model_list[i]) \n", " model.set_train(False)\n", " for data, label in dataset.create_tuple_iterator():\n", " pred = model(data)\n", " pred_probab = nn.Softmax(axis=1)(pred)\n", " # 如果预测概率大于0.55,则预测设为1,否则为0\n", " #pred = pred_probab > 0.55\n", " #pred = np.array(pred).astype(np.int32)\n", " if i == 0:\n", " pred_sum = pred_probab\n", " else:\n", " pred_sum += pred_probab\n", " print(\"finish model {}\".format(i+1))\n", " pred_sum = pred_sum / num_model\n", " pred_sum = pred_sum > 0.55\n", " correct = 0\n", " for i in range(len(pred_sum)):\n", " if (pred_sum[i] == label[i]).all():\n", " correct += 1\n", " correct /= len(pred_sum)\n", " print(f\"Test: \\n Accuracy: {(100*correct):>0.1f}%\")\n", " return pred_sum" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "pred=acc(model_list, testset)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# 将out-of-fold的结果和groundtruth label按3:7混合作为训练新模型的标签,简单的描述即为给每个软化了之前的标签,给与每个标签一定的概率,进而减少了模型训练的难度\n", "def soft_label(label, pred):\n", " label = np.array(label)\n", " pred = np.array(pred)\n", " label = label * 0.3 + pred * 0.7\n", " return label\n", "# 预测val集,并将soft label和groundtruth label混合并保存为csv文件\n", "def val_pred(model, dataset):\n", " num_batches = dataset.get_dataset_size()\n", " for data, label in dataset.create_tuple_iterator():\n", " pred = model(data)\n", " pred_probab = nn.Softmax(axis=1)(pred)\n", " soft_label = soft_label(label, pred_probab)\n", " df = pd.DataFrame(data,soft_label)\n", " df.to_csv('soft_label.csv', mode='a', header=False)\n", "val_pred(se_resnext, dataset_val)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.8.12 ('torch')", "language": "python", "name": "python3" }, "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.12" }, "orig_nbformat": 4, "vscode": { "interpreter": { "hash": "c65094271e18768ba853ee00da8ef0989016e0be5b6a976cebf700525936202a" } } }, "nbformat": 4, "nbformat_minor": 2 }