{"metadata": {"language_info": {"pygments_lexer": "ipython3", "version": "3.6.3", "mimetype": "text/x-python", "name": "python", "codemirror_mode": {"version": 3, "name": "ipython"}, "nbconvert_exporter": "python", "file_extension": ".py"}, "kernelspec": {"language": "python", "name": "python3", "display_name": "Python 3"}}, "nbformat": 4, "cells": [{"source": ["# Pytorch ResNeXT  + DataLoader, Kaggle TF Audio Classification LB 0.65\n", "\n", "![curve](https://github.com/QuantScientist/Deep-Learning-Boot-Camp/raw/master/Kaggle-PyTorch/ResNeXt_2017-12-04_21-59-36.png)\n", "\n", "## Credits\n", "- Audio feature generation was directly copied from here https://github.com/adiyoss/GCommandsPytorch \n", "- You should also run https://github.com/adiyoss/GCommandsPytorch/blob/master/make_dataset.py **prior** to running my script\n", "\n", "## Features\n", "- Runs fast on a **GPU**\n", "- Generates ACC/LOSS curves in ./log/ directory \n", "- I stopped at **15 Epochs, will try more overnight**\n", "- Work in progress, will try 5 different nets and see how it performs\n", "\n", "# Todo:\n", "- Training was done on 30 classes, should be limited to 10\n", "- Inference (**done**)\n", "- Submission (**done**)\n", "\n", "https://github.com/QuantScientist/Deep-Learning-Boot-Camp/tree/master/Kaggle-PyTorch\n", "\n", "Shlomo Kashani. \n"], "metadata": {"_cell_guid": "74d3d7b0-1f39-4b00-ad03-d08d47e1e7a0", "_uuid": "de2a31a8f5131f6f4bef1dbffd325f5ce87e4ceb"}, "cell_type": "markdown"}, {"source": ["from __future__ import print_function\n", "\n", "import time\n", "\n", "import matplotlib\n", "import torch.nn as nn\n", "import torch.nn.init as init\n", "\n", "matplotlib.use('Agg')\n", "import matplotlib.pyplot as plt\n", "import os\n", "import datetime\n", "import pandas as pd\n", "from torch.utils.data import TensorDataset\n", "\n", "import torch.nn.parallel\n", "from sklearn.utils import shuffle\n", "from torch.autograd import Variable\n", "from torch.utils.data import TensorDataset\n", "from torchvision.transforms import *\n", "import argparse\n", "import csv\n", "import os\n", "import os.path\n", "import shutil\n", "import time\n", "from tqdm import tqdm\n", "import numpy as np\n", "import torch\n", "import torch.backends.cudnn as cudnn\n", "import torch.nn as nn\n", "import torch.nn.parallel\n", "import torch.optim as optim\n", "import torch.utils.data as data\n", "import torchvision.datasets as datasets\n", "import torchvision.models as models\n", "import torchvision.transforms as transforms\n", "from PIL import Image\n", "\n", "import datetime\n", "import random\n", "\n", "# model_names = sorted(name for name in nnmodels.__dict__ if name.islower() and not name.startswith(\"__\"))\n", "\n", "parser = argparse.ArgumentParser(description='PyTorch SENet for TF commands')\n", "\n", "parser.add_argument('--dataset', type=str, default='tf', choices=['tf'], help='Choose between data sets')\n", "parser.add_argument('--train_path', default='d:/db/data/tf/2018/train', help='path to the train data folder')\n", "parser.add_argument('--test_path', default='d:/db/data/tf/2018/test', help='path to the test data folder')\n", "parser.add_argument('--valid_path', default='d:/db/data/tf/2018/valid', help='path to the valid data folder')\n", "parser.add_argument('--test_audio', default='d:/db/data/tf/test/audio/', help='path to the valid data folder')\n", "\n", "\n", "\n", "parser.add_argument('--save_path', type=str, default='./log/', help='Folder to save checkpoints and log.')\n", "parser.add_argument('--save_path_model', type=str, default='./log/', help='Folder to save checkpoints and log.')\n", "\n", "parser.add_argument('--epochs', default=15, type=int, metavar='N', help='number of total epochs to run')\n", "parser.add_argument('--start-epoch', default=0, type=int, metavar='N', help='manual epoch number (useful on restarts)')\n", "parser.add_argument('-b', '--batch-size', default=16, type=int, metavar='N', help='mini-batch size (default: 256)')\n", "parser.add_argument('--lr', '--learning-rate', default=0.00005 * 2 * 2 , type=float, metavar='LR', help='initial learning rate')\n", "parser.add_argument('--momentum', default=0.9, type=float, metavar='M', help='momentum')\n", "parser.add_argument('--weight-decay', default=1e-4, type=float, metavar='W', help='weight decay')\n", "parser.add_argument('--print-freq', default=400, type=int, metavar='N', help='print frequency')\n", "parser.add_argument('--test', default=True, help='evaluate model on test set')\n", "\n", "parser.add_argument('--validationRatio', type=float, default=0.11, help='test Validation Split.')\n", "parser.add_argument('--optim', type=str, default='adam', help='Adam or SGD')\n", "parser.add_argument('--imgDim', default=3, type=int, help='number of Image input dimensions')\n", "parser.add_argument('--img_scale', default=224, type=int, help='Image scaling dimensions')\n", "parser.add_argument('--base_factor', default=20, type=int, help='SENet base factor')\n", "\n", "parser.add_argument('--current_time', type=str, default=datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S'),help='Current time.')\n", "parser.add_argument('--ngpu', type=int, default=1, help='0 = CPU.')\n", "parser.add_argument('--workers', type=int, default=0, help='number of data loading workers (default: 0)')\n", "# random seed\n", "parser.add_argument('--manualSeed', type=int, default=999, help='manual seed')\n", "\n", "\n", "\n", "\n", "# feature extraction options\n", "parser.add_argument('--window_size', default=.02, help='window size for the stft')\n", "parser.add_argument('--window_stride', default=.01, help='window stride for the stft')\n", "parser.add_argument('--window_type', default='hamming', help='window type for the stft')\n", "parser.add_argument('--normalize', default=True, help='boolean, wheather or not to normalize the spect')\n", "\n", "import librosa\n", "import numpy as np\n", "\n", "AUDIO_EXTENSIONS = [\n", "    '.wav', '.WAV',\n", "]\n", "\n", "args = parser.parse_args()\n", "\n", "state = {k: v for k, v in args._get_kwargs()}\n", "\n", "if not os.path.isdir(args.save_path):\n", "    os.makedirs(args.save_path)\n", "\n", "def fixSeed(args):\n", "    random.seed(args.manualSeed)\n", "    np.random.seed(args.manualSeed)\n", "    torch.manual_seed(args.manualSeed)\n", "    if args.use_cuda:\n", "        torch.cuda.manual_seed(args.manualSeed)\n", "        torch.cuda.manual_seed_all(args.manualSeed)\n", "\n", "# Use CUDA\n", "args = parser.parse_args()\n", "args.use_cuda = args.ngpu > 0 and torch.cuda.is_available()\n", "use_cuda = args.use_cuda\n", "\n", "if args.manualSeed is None:\n", "    args.manualSeed = 999\n", "fixSeed(args)\n", "\n", "\n", "\n", "import librosa\n", "import numpy as np\n", "import librosa\n", "import numpy as np\n", "\n", "AUDIO_EXTENSIONS = [\n", "    '.wav', '.WAV',\n", "]\n", "\n", "\n", "def is_audio_file(filename):\n", "    return any(filename.endswith(extension) for extension in AUDIO_EXTENSIONS)\n", "\n", "\n", "def find_classes(dir):\n", "    classes = [d for d in os.listdir(dir) if os.path.isdir(os.path.join(dir, d))]\n", "    classes.sort()\n", "    class_to_idx = {classes[i]: i for i in range(len(classes))}\n", "    num_to_class = dict(zip(range(len(classes)), classes))\n", "    return classes, class_to_idx, num_to_class\n", "\n", "\n", "\n", "\n", "def make_dataset(dir, class_to_idx):\n", "    spects = []\n", "    dir = os.path.expanduser(dir)\n", "    for target in sorted(os.listdir(dir)):\n", "        d = os.path.join(dir, target)\n", "        if not os.path.isdir(d):\n", "            continue\n", "\n", "        for root, _, fnames in sorted(os.walk(d)):\n", "            for fname in sorted(fnames):\n", "                if is_audio_file(fname):\n", "                    path = os.path.join(root, fname)\n", "                    item = (path, class_to_idx[target])\n", "                    spects.append(item)\n", "    return spects\n", "\n", "\n", "def spect_loader(path, window_size, window_stride, window, normalize, max_len=101):\n", "    y, sr = librosa.load(path, sr=None)\n", "    # n_fft = 4096\n", "    n_fft = int(sr * window_size)\n", "    win_length = n_fft\n", "    hop_length = int(sr * window_stride)\n", "\n", "    # STFT\n", "    D = librosa.stft(y, n_fft=n_fft, hop_length=hop_length,\n", "                     win_length=win_length, window=window)\n", "    spect, phase = librosa.magphase(D)\n", "\n", "    # S = log(S+1)\n", "    spect = np.log1p(spect)\n", "\n", "    # make all spects with the same dims\n", "    # TODO: change that in the future\n", "    if spect.shape[1] < max_len:\n", "        pad = np.zeros((spect.shape[0], max_len - spect.shape[1]))\n", "        spect = np.hstack((spect, pad))\n", "    elif spect.shape[1] > max_len:\n", "        spect = spect[:max_len, ]\n", "    spect = np.resize(spect, (1, spect.shape[0], spect.shape[1]))\n", "    spect = torch.FloatTensor(spect)\n", "\n", "    # z-score normalization\n", "    if normalize:\n", "        mean = spect.mean()\n", "        std = spect.std()\n", "        if std != 0:\n", "            spect.add_(-mean)\n", "            spect.div_(std)\n", "\n", "    return spect\n", "\n", "\n", "class TFAudioDataSet(data.Dataset):\n", "    def __init__(self, root, transform=None, target_transform=None, window_size=.02,\n", "                 window_stride=.01, window_type='hamming', normalize=True, max_len=101):\n", "        classes, class_to_idx, idx_to_class = find_classes(root)\n", "        spects = make_dataset(root, class_to_idx)\n", "        if len(spects) == 0:\n", "            raise (RuntimeError(\n", "                \"Found 0 sound files in subfolders of: \" + root + \"Supported audio file extensions are: \" + \",\".join(\n", "                    AUDIO_EXTENSIONS)))\n", "\n", "        self.root = root\n", "        self.spects = spects\n", "        self.classes = classes\n", "        self.class_to_idx = class_to_idx\n", "        self.transform = transform\n", "        self.target_transform = target_transform\n", "        self.loader = spect_loader\n", "        self.window_size = window_size\n", "        self.window_stride = window_stride\n", "        self.window_type = window_type\n", "        self.normalize = normalize\n", "        self.max_len = max_len\n", "\n", "    def __getitem__(self, index):\n", "        \"\"\"\n", "        Args:\n", "            index (int): Index\n", "        Returns:\n", "            tuple: (spect, target) where target is class_index of the target class.\n", "        \"\"\"\n", "        path, target = self.spects[index]\n", "        spect = self.loader(path, self.window_size, self.window_stride, self.window_type, self.normalize, self.max_len)\n", "        if self.transform is not None:\n", "            spect = self.transform(spect)\n", "        if self.target_transform is not None:\n", "            target = self.target_transform(target)\n", "\n", "        return spect, target\n", "\n", "    def __len__(self):\n", "        return len(self.spects)\n", "\n", "\n", "'''ResNeXt in PyTorch.\n", "\n", "See the paper \"Aggregated Residual Transformations for Deep Neural Networks\" for more details.\n", "'''\n", "import torch\n", "import torch.nn as nn\n", "import torch.nn.functional as F\n", "\n", "from torch.autograd import Variable\n", "\n", "\n", "class ConvCNN(nn.Module):\n", "    def __init__(self, insize, outsize, kernel_size=7, padding=2, pool=2, avg=True):\n", "        super(ConvCNN, self).__init__()\n", "        self.avg = avg\n", "        self.math = torch.nn.Sequential(\n", "            torch.nn.Conv2d(insize, outsize, kernel_size=kernel_size, padding=padding),\n", "            torch.nn.BatchNorm2d(outsize),\n", "            torch.nn.LeakyReLU(),\n", "            torch.nn.MaxPool2d(pool, pool),\n", "        )\n", "        self.avgpool = torch.nn.AvgPool2d(pool, pool)\n", "\n", "    def forward(self, x):\n", "        x = self.math(x)\n", "        if self.avg is True:\n", "            x = self.avgpool(x)\n", "        return x\n", "\n", "\n", "class Block(nn.Module):\n", "    '''Grouped convolution block.'''\n", "    expansion = 2\n", "\n", "    def __init__(self, in_planes, cardinality=32, bottleneck_width=4, stride=1):\n", "        super(Block, self).__init__()\n", "        group_width = cardinality * bottleneck_width\n", "        self.conv1 = nn.Conv2d(in_planes, group_width, kernel_size=1, bias=False)\n", "        self.bn1 = nn.BatchNorm2d(group_width)\n", "        self.conv2 = nn.Conv2d(group_width, group_width, kernel_size=3, stride=stride, padding=1, groups=cardinality,\n", "                               bias=False)\n", "        self.bn2 = nn.BatchNorm2d(group_width)\n", "        self.conv3 = nn.Conv2d(group_width, self.expansion * group_width, kernel_size=1, bias=False)\n", "        self.bn3 = nn.BatchNorm2d(self.expansion * group_width)\n", "\n", "        self.shortcut = nn.Sequential()\n", "        if stride != 1 or in_planes != self.expansion * group_width:\n", "            self.shortcut = nn.Sequential(\n", "                nn.Conv2d(in_planes, self.expansion * group_width, kernel_size=1, stride=stride, bias=False),\n", "                nn.BatchNorm2d(self.expansion * group_width)\n", "            )\n", "\n", "    def forward(self, x):\n", "        out = F.relu(self.bn1(self.conv1(x)))\n", "        out = F.relu(self.bn2(self.conv2(out)))\n", "        out = self.bn3(self.conv3(out))\n", "        out += self.shortcut(x)\n", "        out = F.relu(out)\n", "        return out\n", "\n", "\n", "class ResNeXt(nn.Module):\n", "    def __init__(self, num_blocks, cardinality, bottleneck_width, num_classes=30):\n", "        super(ResNeXt, self).__init__()\n", "        self.cardinality = cardinality\n", "        self.bottleneck_width = bottleneck_width\n", "        self.in_planes = 64\n", "\n", "        self.conv1 = nn.Conv2d(1, 64, kernel_size=1, bias=False)\n", "        self.bn1 = nn.BatchNorm2d(64)\n", "        self.layer1 = self._make_layer(num_blocks[0], 1)\n", "        self.layer2 = self._make_layer(num_blocks[1], 2)\n", "        self.layer3 = self._make_layer(num_blocks[2], 2)\n", "        # self.layer4 = self._make_layer(num_blocks[3], 2)\n", "\n", "        # self.linear = nn.Linear(cardinality*bottleneck_width*8, num_classes)\n", "        self.linear = nn.Linear(3840, num_classes)\n", "\n", "        self.sig = nn.Sigmoid()\n", "\n", "    def _make_layer(self, num_blocks, stride):\n", "        strides = [stride] + [1] * (num_blocks - 1)\n", "        layers = []\n", "        for stride in strides:\n", "            layers.append(Block(self.in_planes, self.cardinality, self.bottleneck_width, stride))\n", "            self.in_planes = Block.expansion * self.cardinality * self.bottleneck_width\n", "        # Increase bottleneck_width by 2 after each stage.\n", "        self.bottleneck_width *= 2\n", "        return nn.Sequential(*layers)\n", "\n", "    def forward(self, x):\n", "        out = F.relu(self.bn1(self.conv1(x)))\n", "        out = self.layer1(out)\n", "        out = self.layer2(out)\n", "        out = self.layer3(out)\n", "        # out = self.layer4(out)\n", "        out = F.avg_pool2d(out, 8)\n", "        out = out.view(out.size(0), -1)\n", "        # print (out.data.shape)\n", "        out = self.linear(out)\n", "        # out = F.log_softmax(out)\n", "        # out = self.sig(out)\n", "        return out\n", "\n", "\n", "def ResNeXt29_2x64d():\n", "    return ResNeXt(num_blocks=[1, 1, 1], cardinality=4, bottleneck_width=8)\n", "\n", "\n", "def ResNeXt29_4x64d():\n", "    return ResNeXt(num_blocks=[3, 3, 3], cardinality=4, bottleneck_width=64)\n", "\n", "\n", "def ResNeXt29_8x64d():\n", "    return ResNeXt(num_blocks=[3, 3, 3], cardinality=8, bottleneck_width=64)\n", "\n", "\n", "def ResNeXt29_32x4d():\n", "    return ResNeXt(num_blocks=[3, 3, 3], cardinality=32, bottleneck_width=4)\n", "\n", "best_prec1 = 0\n", "\n", "\n", "def main():\n", "    global args, best_prec1\n", "\n", "    if not os.path.isdir(args.save_path):\n", "        os.makedirs(args.save_path)\n", "    # fixSeed(args)\n", "\n", "    resnet = ResNeXt29_2x64d()\n", "    # model = models.__dict__[args.arch]()\n", "    model = resnet\n", "    model_name = (type(model).__name__)\n", "\n", "    mPath = args.save_path + '/' + args.dataset + '/' + model_name + '/'\n", "    args.save_path_model = mPath\n", "    if not os.path.isdir(args.save_path_model):\n", "        mkdir_p(args.save_path_model)\n", "\n", "    print(\"Ensemble with model {}:\".format(model_name))\n", "    print('Save path : {}'.format(args.save_path_model))\n", "    print(state)\n", "    print(\"Random Seed: {}\".format(args.manualSeed))\n", "    import sys\n", "    print(\"python version : {}\".format(sys.version.replace('\\n', ' ')))\n", "    print(\"torch  version : {}\".format(torch.__version__))\n", "    print(\"cudnn  version : {}\".format(torch.backends.cudnn.version()))\n", "    print(\"=> Final model name '{}'\".format(model_name))\n", "    # print_log(\"=> Full model '{}'\".format(model), log)\n", "    # model = torch.nn.DataParallel(model).cuda()\n", "    model.cuda()\n", "    cudnn.benchmark = True\n", "    print('    Total params: %.2fM' % (sum(p.numel() for p in model.parameters()) / 1000000.0))\n", "    print('Batch size : {}'.format(args.batch_size))\n", "\n", "    if args.use_cuda:\n", "        model.cuda()\n", "        # model = torch.nn.DataParallel(model).cuda()\n", "\n", "    cudnn.benchmark = True\n", "    # Data loading code\n", "    train_dataset = TFAudioDataSet(args.train_path, window_size=args.window_size, window_stride=args.window_stride,\n", "                                   window_type=args.window_type, normalize=args.normalize)\n", "    train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True, num_workers=0,\n", "                                               pin_memory=False, sampler=None)\n", "    valid_dataset = TFAudioDataSet(args.valid_path, window_size=args.window_size, window_stride=args.window_stride,\n", "                                   window_type=args.window_type, normalize=args.normalize)\n", "    val_loader = torch.utils.data.DataLoader(valid_dataset, batch_size=args.batch_size, shuffle=None, num_workers=0,\n", "                                               pin_memory=False, sampler=None)\n", "    test_dataset = TFAudioDataSet(args.test_path, window_size=args.window_size, window_stride=args.window_stride,\n", "                                  window_type=args.window_type, normalize=args.normalize)\n", "\n", "    test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=args.batch_size, shuffle=None,\n", "                                              num_workers=0,\n", "                                              pin_memory=False, sampler=None)\n", "\n", "    # define loss function (criterion)\n", "    criterion = nn.CrossEntropyLoss()\n", "    if args.use_cuda:\n", "        criterion.cuda()\n", "\n", "    optimizer = optim.Adam(model.parameters(), args.lr, weight_decay=args.weight_decay)\n", "    recorder = RecorderMeter(args.epochs)  # epoc is updated\n", "    runId = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')\n", "\n", "    if args.test:\n", "        print(\"Testing the model and generating  output csv for submission\")\n", "        s_submission = pd.read_csv('tf-sample-submission.csv')\n", "        s_submission.columns = ['fname', 'label']\n", "\n", "        checkpoint = torch.load('./log/tf/ResNeXt/checkpoint.pth.tar')\n", "        model.load_state_dict(checkpoint['state_dict'])\n", "\n", "        df_pred= testModel (args.test_audio, model, s_submission)\n", "        pre = args.save_path_model + '/' + '/pth/'\n", "        if not os.path.isdir(pre):\n", "            os.makedirs(pre)\n", "        fName = pre + str('.83')\n", "        # torch.save(model.state_dict(), fName + '_cnn.pth')\n", "        csv_path = str(fName + '_submission.csv')\n", "        df_pred.to_csv(csv_path, columns=('fname', 'label'), index=None)\n", "        print(csv_path)\n", "\n", "        return\n", "\n", "\n", "        # for epoch in range(args.start_epoch, args.epochs):\n", "    for epoch in tqdm(range(args.start_epoch, args.epochs)):\n", "        # adjust_learning_rate(optimizer, epoch)\n", "        # train for one epoch\n", "        tqdm.write('\\n==>>Epoch=[{:03d}/{:03d}]], LR=[{}], Batch=[{}]'.format(epoch, args.epochs,\n", "                                                                                    state['lr'],\n", "            args.batch_size) + ' [Model={}]'.format(\n", "            (type(model).__name__), ))\n", "\n", "        train_result, accuracy_tr=train(train_loader, model, criterion, optimizer, epoch)\n", "        # evaluate on validation set\n", "        val_result, accuracy_val = validate(val_loader, model, criterion)\n", "\n", "        recorder.update(epoch, train_result, accuracy_tr, val_result, accuracy_val)\n", "        mPath = args.save_path_model + '/'\n", "        if not os.path.isdir(mPath):\n", "            os.makedirs(mPath)\n", "        recorder.plot_curve(os.path.join(mPath, model_name + '_' + runId + '.png'), args, model)\n", "\n", "        # remember best Accuracy and save checkpoint\n", "        is_best = accuracy_val > best_prec1\n", "        best_prec1 = max(accuracy_val, best_prec1)\n", "        save_checkpoint({\n", "            'epoch': epoch + 1,\n", "            'state_dict': model.state_dict(),\n", "            'best_prec1': best_prec1,\n", "        }, is_best, best_prec1)\n", "\n", "    test_loss, test_acc = validate(test_loader, model, criterion)\n", "    print('Test: {}, {}'.format(test_loss, test_acc))\n", "\n", "def testAudioLoader(image_name):\n", "    \"\"\"load image, returns cuda tensor\"\"\"\n", "#     image = Image.open(image_name)\n", "    image = spect_loader(image_name, args.window_size, args.window_stride, args.window_type, args.normalize, max_len=101)\n", "#     image = Variable(image, requires_grad=True)\n", "    image = image.unsqueeze(0)\n", "    if args.use_cuda:\n", "        image.cuda()\n", "    return image\n", "\n", "def testModel(test_dir, local_model, sample_submission):\n", "    print ('Testing model: {}'.format(str(local_model)))\n", "\n", "    classes, class_to_idx, idx_to_class = find_classes(args.train_path)\n", "\n", "    if args.use_cuda:\n", "        local_model.cuda()\n", "    local_model.eval()\n", "\n", "    columns = ['fname', 'label']\n", "    df_pred = pd.DataFrame(data=np.zeros((0, len(columns))), columns=columns)\n", "    #     df_pred.species.astype(int)\n", "    for index, row in (sample_submission.iterrows()):\n", "        #         for file in os.listdir(test_dir):\n", "        currImage = os.path.join(test_dir, row['fname'])\n", "        if os.path.isfile(currImage):\n", "            print (currImage)\n", "            X_tensor_test = testAudioLoader(currImage)\n", "            #             print (type(X_tensor_test))\n", "            if args.use_cuda:\n", "                X_tensor_test = Variable(X_tensor_test.cuda())\n", "            else:\n", "                X_tensor_test = Variable(X_tensor_test)\n", "            predicted_val = (local_model(X_tensor_test)).data.max(1)[1]  # get the index of the max log-probability\n", "            p_test = (predicted_val.cpu().numpy().item())\n", "            df_pred = df_pred.append({'fname': row['fname'], 'label': idx_to_class[int(p_test)]}, ignore_index=True)\n", "\n", "    print('Testing model done: {}'.format(str(df_pred.shape)))\n", "    return df_pred\n", "\n", "def train(train_loader, model, criterion, optimizer, epoch):\n", "    batch_time = AverageMeter()\n", "    data_time = AverageMeter()\n", "    losses = AverageMeter()\n", "    acc = AverageMeter()\n", "\n", "    # switch to train mode\n", "    model.train()\n", "\n", "    end = time.time()\n", "    for i, (images, target) in enumerate(train_loader):\n", "        # measure data loading time\n", "        data_time.update(time.time() - end)\n", "\n", "        if use_cuda:\n", "            images, target = images.cuda(), target.cuda()\n", "            images, target = Variable(images), Variable(target)\n", "\n", "        # compute y_pred\n", "        y_pred = model(images)\n", "        loss = criterion(y_pred, target)\n", "\n", "        # measure accuracy and record loss\n", "        prec1, prec1 = accuracy(y_pred.data, target.data, topk=(1, 1))\n", "        losses.update(loss.data[0], images.size(0))\n", "        acc.update(prec1[0], images.size(0))\n", "\n", "        # compute gradient and do SGD step\n", "        optimizer.zero_grad()\n", "        loss.backward()\n", "        optimizer.step()\n", "\n", "        # measure elapsed time\n", "        batch_time.update(time.time() - end)\n", "        end = time.time()\n", "\n", "        if i % args.print_freq == 0:\n", "            print('TRAIN: LOSS-->{loss.val:.4f} ({loss.avg:.4f})\\t' 'ACC-->{acc.val:.3f}% ({acc.avg:.3f}%)'.format(loss=losses, acc=acc))\n", "\n", "    return  float('{loss.avg:.4f}'.format(loss=losses)), float('{acc.avg:.4f}'.format(acc=acc))\n", "\n", "def validate(val_loader, model, criterion):\n", "    batch_time = AverageMeter()\n", "    losses = AverageMeter()\n", "    acc = AverageMeter()\n", "\n", "    # switch to evaluate mode\n", "    model.eval()\n", "\n", "    end = time.time()\n", "    for i, (images, labels) in enumerate(val_loader):\n", "\n", "        if use_cuda:\n", "            images, labels = images.cuda(), labels.cuda()\n", "        images, labels = Variable(images, volatile=True), Variable(labels)\n", "\n", "        # compute y_pred\n", "        y_pred = model(images)\n", "        loss = criterion(y_pred, labels)\n", "\n", "        # measure accuracy and record loss\n", "        prec1, temp_var = accuracy(y_pred.data, labels.data, topk=(1, 1))\n", "        losses.update(loss.data[0], images.size(0))\n", "        acc.update(prec1[0], images.size(0))\n", "\n", "        # measure elapsed time\n", "        batch_time.update(time.time() - end)\n", "        end = time.time()\n", "\n", "        if i % args.print_freq == 0:\n", "            print('VAL:   LOSS--> {loss.val:.4f} ({loss.avg:.4f})\\t''ACC-->{acc.val:.3f} ({acc.avg:.3f})'.format(loss=losses, acc=acc))\n", "    print(' * Accuracy {acc.avg:.3f}'.format(acc=acc))\n", "    return float('{loss.avg:.4f}'.format(loss=losses)), float('{acc.avg:.4f}'.format(acc=acc))\n", "\n", "\n", "def save_checkpoint(state, is_best, acc):\n", "    filename= args.save_path_model + '/' + str(acc) + '_checkpoint.pth.tar'\n", "    torch.save(state, filename)\n", "    if is_best:\n", "        shutil.copyfile(filename, 'model_best.pth.tar')\n", "\n", "class AverageMeter(object):\n", "    \"\"\"Computes and stores the average and current value\"\"\"\n", "\n", "    def __init__(self):\n", "        self.reset()\n", "\n", "    def reset(self):\n", "        self.val = 0\n", "        self.avg = 0\n", "        self.sum = 0\n", "        self.count = 0\n", "\n", "    def update(self, val, n=1):\n", "        self.val = val\n", "        self.sum += val * n\n", "        self.count += n\n", "        self.avg = self.sum / self.count\n", "\n", "\n", "def adjust_learning_rate(optimizer, epoch):\n", "    \"\"\"Sets the learning rate to the initial LR decayed by 10 every 30 epochs\"\"\"\n", "    lr = args.lr * (0.1**(epoch // 30))\n", "    for param_group in optimizer.state_dict()['param_groups']:\n", "        param_group['lr'] = lr\n", "\n", "\n", "def accuracy(y_pred, y_actual, topk=(1, )):\n", "    \"\"\"Computes the precision@k for the specified values of k\"\"\"\n", "    maxk = max(topk)\n", "    batch_size = y_actual.size(0)\n", "\n", "    _, pred = y_pred.topk(maxk, 1, True, True)\n", "    pred = pred.t()\n", "    correct = pred.eq(y_actual.view(1, -1).expand_as(pred))\n", "\n", "    res = []\n", "    for k in topk:\n", "        correct_k = correct[:k].view(-1).float().sum(0)\n", "        res.append(correct_k.mul_(100.0 / batch_size))\n", "\n", "    return res\n", "\n", "\n", "class TestImageFolder(data.Dataset):\n", "    def __init__(self, root, transform=None):\n", "        images = []\n", "        for filename in os.listdir(root):\n", "            if filename.endswith('jpg'):\n", "                images.append('{}'.format(filename))\n", "\n", "        self.root = root\n", "        self.imgs = images\n", "        self.transform = transform\n", "\n", "    def __getitem__(self, index):\n", "        filename = self.imgs[index]\n", "        img = Image.open(os.path.join(self.root, filename))\n", "        if self.transform is not None:\n", "            img = self.transform(img)\n", "        return img, filename\n", "\n", "    def __len__(self):\n", "        return len(self.imgs)\n", "\n", "\n", "import errno\n", "import time\n", "\n", "def mkdir_p(path):\n", "    '''make dir if not exist'''\n", "    try:\n", "        os.makedirs(path)\n", "    except OSError as exc:  # Python >2.5\n", "        if exc.errno == errno.EEXIST and os.path.isdir(path):\n", "            pass\n", "        else:\n", "            raise\n", "\n", "class RecorderMeter(object):\n", "    \"\"\"Computes and stores the minimum loss value and its epoch index\"\"\"\n", "\n", "    def __init__(self, total_epoch):\n", "        self.reset(total_epoch)\n", "\n", "    def reset(self, total_epoch):\n", "        assert total_epoch > 0\n", "        self.total_epoch = total_epoch\n", "        self.current_epoch = 0\n", "        self.epoch_losses = np.zeros((self.total_epoch, 2), dtype=np.float32)  # [epoch, train/val]\n", "        self.epoch_losses = self.epoch_losses - 1\n", "\n", "        self.epoch_accuracy = np.zeros((self.total_epoch, 2), dtype=np.float32)  # [epoch, train/val]\n", "        self.epoch_accuracy = self.epoch_accuracy\n", "\n", "    def update(self, idx, train_loss, train_acc, val_loss, val_acc):\n", "        assert idx >= 0 and idx < self.total_epoch, 'total_epoch : {} , but update with the {} index'.format(\n", "            self.total_epoch, idx)\n", "        self.epoch_losses[idx, 0] = train_loss\n", "        self.epoch_losses[idx, 1] = val_loss\n", "        self.epoch_accuracy[idx, 0] = train_acc\n", "        self.epoch_accuracy[idx, 1] = val_acc\n", "        self.current_epoch = idx + 1\n", "        return self.max_accuracy(False) == val_acc\n", "\n", "    def max_accuracy(self, istrain):\n", "        if self.current_epoch <= 0: return 0\n", "        if istrain:\n", "            return self.epoch_accuracy[:self.current_epoch, 0].max()\n", "        else:\n", "            return self.epoch_accuracy[:self.current_epoch, 1].max()\n", "\n", "    def plot_curve(self, save_path, args, model):\n", "        title = 'PyTorch Model:' + str((type(model).__name__)).upper() + ', DataSet:' + str(args.dataset).upper() + ',' \\\n", "                + 'Params: %.2fM' % (\n", "            sum(p.numel() for p in model.parameters()) / 1000000.0) + ', Seed: %.2f' % args.manualSeed\n", "        dpi = 80\n", "        width, height = 1200, 800\n", "        legend_fontsize = 10\n", "        scale_distance = 48.8\n", "        figsize = width / float(dpi), height / float(dpi)\n", "\n", "        fig = plt.figure(figsize=figsize)\n", "        x_axis = np.array([i for i in range(self.total_epoch)])  # epochs\n", "        y_axis = np.zeros(self.total_epoch)\n", "\n", "        plt.xlim(0, self.total_epoch)\n", "        plt.ylim(0, 1.0)\n", "        interval_y = 0.05 / 3.0\n", "        interval_x = 1\n", "        plt.xticks(np.arange(0, self.total_epoch + interval_x, interval_x))\n", "        plt.yticks(np.arange(0, 1.0 + interval_y, interval_y))\n", "        plt.grid()\n", "        plt.title(title, fontsize=18)\n", "        plt.xlabel('EPOCH', fontsize=16)\n", "        plt.ylabel('LOSS/ACC', fontsize=16)\n", "\n", "        y_axis[:] = self.epoch_accuracy[:, 0] / 100.0\n", "        plt.plot(x_axis, y_axis, color='g', linestyle='-', label='tr-accuracy/100', lw=2)\n", "        plt.legend(loc=4, fontsize=legend_fontsize)\n", "\n", "        y_axis[:] = self.epoch_accuracy[:, 1] / 100.0\n", "        plt.plot(x_axis, y_axis, color='y', linestyle='-', label='val-accuracy/100', lw=2)\n", "        plt.legend(loc=4, fontsize=legend_fontsize)\n", "\n", "        y_axis[:] = self.epoch_losses[:, 0]\n", "        plt.plot(x_axis, y_axis, color='r', linestyle=':', label='tr-loss', lw=2)\n", "        plt.legend(loc=4, fontsize=legend_fontsize)\n", "\n", "        y_axis[:] = self.epoch_losses[:, 1]\n", "        plt.plot(x_axis, y_axis, color='b', linestyle=':', label='val-loss', lw=4)\n", "        plt.legend(loc=4, fontsize=legend_fontsize)\n", "\n", "        if save_path is not None:\n", "            fig.savefig(save_path, dpi=dpi, bbox_inches='tight')\n", "            # print('---- save figure {} into {}'.format(title, save_path))\n", "        plt.close(fig)\n", "\n", "if __name__ == '__main__':\n", "    main()\n"], "metadata": {"collapsed": true, "_cell_guid": "13d9a791-c00b-4f62-a57c-87a7fb4631e6", "_uuid": "ba2f357f9552e5098a84a107bcd70022f40a047d"}, "execution_count": null, "cell_type": "code", "outputs": []}, {"source": [], "metadata": {"collapsed": true, "_cell_guid": "181664ed-235c-472f-8c12-e3023af0d337", "_uuid": "bdb02cc03a8cded9e5af67ca8ad0b5f70e7604bc"}, "execution_count": null, "cell_type": "code", "outputs": []}], "nbformat_minor": 1}