『MXNet』第七弹_分类器demo示意

解压文件命令:

with zipfile.ZipFile(‘../data/kaggle_cifar10/‘ + fin, ‘r‘) as zin:
            zin.extractall(‘../data/kaggle_cifar10/‘)

拷贝文件命令:

shutil.copy(原文件, 目标文件)

整理数据

我们有两个文件夹‘../data/kaggle_cifar10/train‘和‘../data/kaggle_cifar10/test‘,一个记录了文件名和类别的索引文件

我们的目的是在新的文件夹下形成拷贝,包含三个文件夹train_valid、train、valid,每个文件夹下存放不同的类别文件夹,里面存放对应类别的图片,

import os
import shutil

def reorg_cifar10_data(data_dir, label_file, train_dir, test_dir, input_dir, valid_ratio):
    """
    处理之后,新建三个文件夹存放数据,train_valid、train、valid
    data_dir:‘../data/kaggle_cifar10‘
    label_file:‘trainLabels.csv‘
    train_dir = ‘train‘
    test_dir = ‘test‘
    input_dir = ‘train_valid_test‘
    valid_ratio = 0.1
    """
    # 读取训练数据标签。
    # 打开csv索引:‘../data/kaggle_cifar10/trainLabels.csv‘
    with open(os.path.join(data_dir, label_file), ‘r‘) as f:
        # 跳过文件头行(栏名称)。
        lines = f.readlines()[1:]
        tokens = [l.rstrip().split(‘,‘) for l in lines]
        # {索引:标签}
        idx_label = dict(((int(idx), label) for idx, label in tokens))
    # 标签集合
    labels = set(idx_label.values())
    # 训练数据数目:‘../data/kaggle_cifar10/train‘
    num_train = len(os.listdir(os.path.join(data_dir, train_dir)))
    # train数目(对应valid)
    num_train_tuning = int(num_train * (1 - valid_ratio))
    # <---异常检测
    assert 0 < num_train_tuning < num_train
    # 每个label的train数据条目
    num_train_tuning_per_label = num_train_tuning // len(labels)
    label_count = dict()

    def mkdir_if_not_exist(path):
        if not os.path.exists(os.path.join(*path)):
            os.makedirs(os.path.join(*path))

    # 整理训练和验证集。
    # 循环训练数据图片 ‘../data/kaggle_cifar10/train‘
    for train_file in os.listdir(os.path.join(data_dir, train_dir)):
        # 去掉扩展名作为索引
        idx = int(train_file.split(‘.‘)[0])
        # 索引到标签
        label = idx_label[idx]

        # ‘../data/kaggle_cifar10/train_valid_test/train_valid‘ +  标签名称
        mkdir_if_not_exist([data_dir, input_dir, ‘train_valid‘, label])
        # 拷贝图片
        shutil.copy(os.path.join(data_dir, train_dir, train_file),
                    os.path.join(data_dir, input_dir, ‘train_valid‘, label))

        # 保证train文件夹下的每类标签训练数目足够后,分给valid文件夹
        if label not in label_count or label_count[label] < num_train_tuning_per_label:
            # ‘../data/kaggle_cifar10/train_valid_test/train‘ +  标签名称
            mkdir_if_not_exist([data_dir, input_dir, ‘train‘, label])
            shutil.copy(os.path.join(data_dir, train_dir, train_file),
                        os.path.join(data_dir, input_dir, ‘train‘, label))
            label_count[label] = label_count.get(label, 0) + 1
        else:
            mkdir_if_not_exist([data_dir, input_dir, ‘valid‘, label])
            shutil.copy(os.path.join(data_dir, train_dir, train_file),
                        os.path.join(data_dir, input_dir, ‘valid‘, label))

    # 整理测试集
    # ‘../data/kaggle_cifar10/train_valid_test/test/unknown‘ 里面存放test图片
    mkdir_if_not_exist([data_dir, input_dir, ‘test‘, ‘unknown‘])
    for test_file in os.listdir(os.path.join(data_dir, test_dir)):
        shutil.copy(os.path.join(data_dir, test_dir, test_file),
                    os.path.join(data_dir, input_dir, ‘test‘, ‘unknown‘))

train_dir = ‘train‘
test_dir = ‘test‘
batch_size = 128

data_dir = ‘../data/kaggle_cifar10‘
label_file = ‘trainLabels.csv‘
input_dir = ‘train_valid_test‘
valid_ratio = 0.1
reorg_cifar10_data(data_dir, label_file, train_dir, test_dir, input_dir, valid_ratio)

预处理

# 预处理
from mxnet import autograd
from mxnet import gluon
from mxnet import init
from mxnet import nd
from mxnet.gluon.data import vision
from mxnet.gluon.data.vision import transforms
import numpy as np

transform_train = transforms.Compose([
    # transforms.CenterCrop(32)
    # transforms.RandomFlipTopBottom(),
    # transforms.RandomColorJitter(brightness=0.0, contrast=0.0, saturation=0.0, hue=0.0),
    # transforms.RandomLighting(0.0),
    # transforms.Cast(‘float32‘),
    # transforms.Resize(32),

    # 随机按照scale和ratio裁剪,并放缩为32x32的正方形
    transforms.RandomResizedCrop(32, scale=(0.08, 1.0), ratio=(3.0/4.0, 4.0/3.0)),
    # 随机左右翻转图片
    transforms.RandomFlipLeftRight(),
    # 将图片像素值缩小到(0,1)内,并将数据格式从"高*宽*通道"改为"通道*高*宽"
    transforms.ToTensor(),
    # 对图片的每个通道做标准化
    transforms.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010])
])

# 测试时,无需对图像做标准化以外的增强数据处理。
transform_test = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010])
])

# ‘../data/kaggle_cifar10、train_valid_test/‘
input_str = data_dir + ‘/‘ + input_dir + ‘/‘

# 读取原始图像文件。flag=1说明输入图像有三个通道(彩色)。
train_ds = vision.ImageFolderDataset(input_str + ‘train‘, flag=1)
valid_ds = vision.ImageFolderDataset(input_str + ‘valid‘, flag=1)
train_valid_ds = vision.ImageFolderDataset(input_str + ‘train_valid‘, flag=1)
test_ds = vision.ImageFolderDataset(input_str + ‘test‘, flag=1)

loader = gluon.data.DataLoader
train_data = loader(train_ds.transform_first(transform_train),
batch_size, shuffle=True, last_batch=‘keep‘)
valid_data = loader(valid_ds.transform_first(transform_test),
batch_size, shuffle=True, last_batch=‘keep‘)
train_valid_data = loader(train_valid_ds.transform_first(transform_train),
batch_size, shuffle=True, last_batch=‘keep‘)
test_data = loader(test_ds.transform_first(transform_test),
batch_size, shuffle=False, last_batch=‘keep‘)

# 交叉熵损失函数。
softmax_cross_entropy = gluon.loss.SoftmaxCrossEntropyLoss()
mxnet.gluon.vision.ImageFolderDatasetmxnet.gluon.data.DataLoader

数据的预处理放在DataLoader中,这样后面可以调用ImageFolderDataset,获取原始图片集

至此,数据准备完成。

模型定义

from mxnet.gluon import nn
from mxnet import nd

class Residual(nn.HybridBlock):
    def __init__(self, channels, same_shape=True, **kwargs):
        super(Residual, self).__init__(**kwargs)
        self.same_shape = same_shape
        with self.name_scope():
            strides = 1 if same_shape else 2
            self.conv1 = nn.Conv2D(channels, kernel_size=3, padding=1,
                                  strides=strides)
            self.bn1 = nn.BatchNorm()
            self.conv2 = nn.Conv2D(channels, kernel_size=3, padding=1)
            self.bn2 = nn.BatchNorm()
            if not same_shape:
                self.conv3 = nn.Conv2D(channels, kernel_size=1,
                                      strides=strides)

    def hybrid_forward(self, F, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        if not self.same_shape:
            x = self.conv3(x)
        return F.relu(out + x)

class ResNet(nn.HybridBlock):
    def __init__(self, num_classes, verbose=False, **kwargs):
        super(ResNet, self).__init__(**kwargs)
        self.verbose = verbose
        with self.name_scope():
            net = self.net = nn.HybridSequential()
            # 模块1
            net.add(nn.Conv2D(channels=32, kernel_size=3, strides=1, padding=1))
            net.add(nn.BatchNorm())
            net.add(nn.Activation(activation=‘relu‘))
            # 模块2
            for _ in range(3):
                net.add(Residual(channels=32))
            # 模块3
            net.add(Residual(channels=64, same_shape=False))
            for _ in range(2):
                net.add(Residual(channels=64))
            # 模块4
            net.add(Residual(channels=128, same_shape=False))
            for _ in range(2):
                net.add(Residual(channels=128))
            # 模块5
            net.add(nn.AvgPool2D(pool_size=8))
            net.add(nn.Flatten())
            net.add(nn.Dense(num_classes))

    def hybrid_forward(self, F, x):
        out = x
        for i, b in enumerate(self.net):
            out = b(out)
            if self.verbose:
                print(‘Block %d output: %s‘%(i+1, out.shape))
        return out

def get_net(ctx):
    num_outputs = 10
    net = ResNet(num_outputs)
    net.initialize(ctx=ctx, init=init.Xavier())
    return net

训练

gb.accuracy(output, label)
trainer.set_learning_rate(trainer.learning_rate * lr_decay)
gb.evaluate_accuracy(valid_data, net, ctx)
import datetime
import sys
sys.path.append(‘..‘)
import gluonbook as gb

def train(net, train_data, valid_data, num_epochs, lr, wd, ctx, lr_period, lr_decay):
    trainer = gluon.Trainer(
        net.collect_params(), ‘sgd‘, {‘learning_rate‘: lr, ‘momentum‘: 0.9, ‘wd‘: wd})

    prev_time = datetime.datetime.now()
    for epoch in range(num_epochs):
        train_loss = 0.0
        train_acc = 0.0
        if epoch > 0 and epoch % lr_period == 0:
            trainer.set_learning_rate(trainer.learning_rate * lr_decay)
        for data, label in train_data:
            label = label.astype(‘float32‘).as_in_context(ctx)
            with autograd.record():
                output = net(data.as_in_context(ctx))
                loss = softmax_cross_entropy(output, label)
            loss.backward()
            trainer.step(batch_size)
            train_loss += nd.mean(loss).asscalar()
            train_acc += gb.accuracy(output, label)
        cur_time = datetime.datetime.now()
        h, remainder = divmod((cur_time - prev_time).seconds, 3600)
        m, s = divmod(remainder, 60)
        time_str = "Time %02d:%02d:%02d" % (h, m, s)
        if valid_data is not None:
            valid_acc = gb.evaluate_accuracy(valid_data, net, ctx)
            epoch_str = ("Epoch %d. Loss: %f, Train acc %f, Valid acc %f, "
                         % (epoch, train_loss / len(train_data),
                            train_acc / len(train_data), valid_acc))
        else:
            epoch_str = ("Epoch %d. Loss: %f, Train acc %f, "
                         % (epoch, train_loss / len(train_data),
                            train_acc / len(train_data)))
        prev_time = cur_time
        print(epoch_str + time_str + ‘, lr ‘ + str(trainer.learning_rate))  

实际训练起来,

ctx = gb.try_gpu()
num_epochs = 1
learning_rate = 0.1
weight_decay = 5e-4
lr_period = 80
lr_decay = 0.1

net = get_net(ctx)
net.hybridize()
train(net, train_data, valid_data, num_epochs, learning_rate,
      weight_decay, ctx, lr_period, lr_decay)

预测

import numpy as np
import pandas as pd

# 训练
net = get_net(ctx)
net.hybridize()
train(net, train_valid_data, None, num_epochs, learning_rate,
      weight_decay, ctx, lr_period, lr_decay)

# 预测
preds = []
for data, label in test_data:
    output = net(data.as_in_context(ctx))
    preds.extend(output.argmax(axis=1).astype(int).asnumpy())

sorted_ids = list(range(1, len(test_ds) + 1))
sorted_ids.sort(key = lambda x:str(x))

df = pd.DataFrame({‘id‘: sorted_ids, ‘label‘: preds})
df[‘label‘] = df[‘label‘].apply(lambda x: train_valid_ds.synsets[x])
df.to_csv(‘submission.csv‘, index=False)

  

  

原文地址:https://www.cnblogs.com/hellcat/p/9098168.html

时间: 2024-11-06 03:44:56

『MXNet』第七弹_分类器demo示意的相关文章

『MXNet』第六弹_数据处理API(待续)

一.Gluon数据加载 图片数据(含标签)加载函数:gluon.data.vision.ImageFolderDataset 给出ImageFolderDataset类的描述, Init signature: mxnet.gluon.data.vision.datasets.ImageFolderDataset(root, flag=1, transform=None) Source: class ImageFolderDataset(dataset.Dataset): """

『MXNet』第八弹_物体检测之SSD

预.API介绍 mxnet.metric from mxnet import metric cls_metric = metric.Accuracy() box_metric = metric.MAE() cls_metric.update([cls_target], [class_preds.transpose((0,2,1))]) box_metric.update([box_target], [box_preds * box_mask]) cls_metric.get() box_metr

『MXNet』第十一弹_符号式编程专题

一.符号分类 符号对我们想要进行的计算进行了描述, 下图展示了符号如何对计算进行描述. 我们定义了符号变量A, 符号变量B, 生成了符号变量C, 其中, A, B为参数节点, C为内部节点! mxnet.symbol.Variable可以生成参数节点, 用于表示计算时的输入. 二.常用符号方法 一个Symbol具有的属性和方法如下图所示: 关联节点查看 list_argument()用来检查计算图的输入参数; list_output()返回此Symbol的所有输出,输出的自动命名遵循一定的规则

『MXNet』第五弹_多GPU并行程序设计

资料原文 一.概述思路 假设一台机器上有k个GPU.给定需要训练的模型,每个GPU将分别独立维护一份完整的模型参数. 在模型训练的任意一次迭代中,给定一个小批量,我们将该批量中的样本划分成k份并分给每个GPU一份. 然后,每个GPU将分别根据自己分到的训练数据样本和自己维护的模型参数计算模型参数的梯度. 接下来,我们把k个GPU上分别计算得到的梯度相加,从而得到当前的小批量梯度. 之后,每个GPU都使用这个小批量梯度分别更新自己维护的那一份完整的模型参数. 二.网络以及辅助函数 使用“卷积神经网

『PyTorch』第四弹_通过LeNet初识pytorch神经网络_下

『PyTorch』第四弹_通过LeNet初识pytorch神经网络_上 # Author : Hellcat # Time : 2018/2/11 import torch as t import torch.nn as nn import torch.nn.functional as F class LeNet(nn.Module): def __init__(self): super(LeNet,self).__init__() self.conv1 = nn.Conv2d(3, 6, 5)

『PyTorch』第十弹_循环神经网络

『cs231n』作业3问题1选讲_通过代码理解RNN&图像标注训练 对于torch中的RNN相关类,有原始和原始Cell之分,其中RNN和RNNCell层的区别在于前者一次能够处理整个序列,而后者一次只处理序列中一个时间点的数据,前者封装更完备更易于使用,后者更具灵活性.实际上RNN层的一种后端实现方式就是调用RNNCell来实现的. 一.nn.RNN import torch as t from torch import nn from torch.autograd import Variab

『PyTorch』第三弹_自动求导

torch.autograd 包提供Tensor所有操作的自动求导方法. 数据结构介绍 autograd.Variable 这是这个包中最核心的类. 它包装了一个Tensor,并且几乎支持所有的定义在其上的操作.一旦完成了你的运算,你可以调用 .backward()来自动计算出所有的梯度,Variable有三个属性: 访问原始的tensor使用属性.data: 关于这一Variable的梯度则集中于 .grad: .creator反映了创建者,标识了是否由用户使用.Variable直接创建(No

『PyTorch』第五弹_深入理解Tensor对象_中上:索引

一.普通索引 示例 a = t.Tensor(4,5) print(a) print(a[0:1,:2]) print(a[0,:2]) # 注意和前一种索引出来的值相同,shape不同 print(a[[1,2]]) # 容器索引 3.3845e+15 0.0000e+00 3.3846e+15 0.0000e+00 3.3845e+15 0.0000e+00 3.3845e+15 0.0000e+00 3.3418e+15 0.0000e+00 3.3845e+15 0.0000e+00 3

『PyTorch』第五弹_深入理解Tensor对象_中下:数学计算以及numpy比较

一.简单数学操作 1.逐元素操作 t.clamp(a,min=2,max=4)近似于tf.clip_by_value(A, min, max),修剪值域. a = t.arange(0,6).view(2,3) print("a:",a) print("t.cos(a):",t.cos(a)) print("a % 3:",a % 3) # t.fmod(a, 3) print("a ** 2:",a ** 2) # t.po