飞桨领航团图像分类零基础训练营学习笔记

课程链接:https://aistudio.baidu.com/aistudio/course/introduce/11939?directly=1&shared=1

第一课作业

   补齐代码,完成图像增广。 

在这里插入图片描述

1.图片缩放

class Resize:
    def __init__(self, size):
        self.size=size

    def __call__(self, img):
        return cv2.resize(img,self.size)

在这里插入图片描述

2.图片翻转

class Flip:
    def __init__(self, mode):
        self.mode=mode

    def __call__(self, img):

        return cv2.flip(img, 0)

在这里插入图片描述

3.图片旋转

class Rotate:
    def __init__(self, degree,size):
        self.degree=degree
        self.size=size

    def __call__(self, img):

        rows, cols,x = img.shape
        M = cv2.getRotationMatrix2D((cols/ 2.0, rows/ 2.0), self.degree, self.size)
        return cv2.warpAffine(img, M, (cols, rows))

在这里插入图片描述

4.图片亮度调节

class Brightness:
    def __init__(self,brightness_factor):
        self.brightness_factor=brightness_factor

    def __call__(self, img):

        rows, cols, x = img.shape
        a = 1
        blank = np.zeros([rows, cols, x], img.dtype)
        return cv2.addWeighted(img, a, blank, 1-a, self.brightness_factor * 100)

在这里插入图片描述

5.图片随机裁剪

import random
import math

class RandomErasing(object):
    def __init__(self, EPSILON=0.5, sl=0.02, sh=0.4, r1=0.3,
                 mean=[0., 0., 0.]):
        self.EPSILON = EPSILON
        self.mean = mean
        self.sl = sl
        self.sh = sh
        self.r1 = r1

    def __call__(self, img):
        if random.uniform(0, 1) > self.EPSILON:
            return img

        for attempt in range(100):
            area = img.shape[0] * img.shape[1]

            target_area = random.uniform(self.sl, self.sh) * area
            aspect_ratio = random.uniform(self.r1, 1 / self.r1)

            h = int(round(math.sqrt(target_area * aspect_ratio)))
            w = int(round(math.sqrt(target_area / aspect_ratio)))

            
            if h < img.shape[0] and w < img.shape[1]:
                x1 = random.randint(0, img.shape[0] - h)
                y1 = random.randint(0, img.shape[1] - w)
                if img.shape[2] == 3:
                    img[ x1:x1 + h, y1:y1 + w, 0] = self.mean[0]
                    img[ x1:x1 + h, y1:y1 + w, 1] = self.mean[1]
                    img[ x1:x1 + h, y1:y1 + w, 2] = self.mean[2]
                else:
                    img[x1:x1 + h, y1:y1 + w,0] = self.mean[0]
                return img


        return img


erase = RandomErasing()
img2=erase(img)
             return img


        return img

在这里插入图片描述

第二课作业

作业要求: 
1.补全网络代码,并运行手写数字识别项目。以出现最后的图片和预测结果为准。
2.保留原本的multilayer_perceptron网络定义,自己定义一个卷积网络并运行成功。以出现最后的图片和预测结果为准。

1.导入需要的包

#导入需要的包
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import os
import paddle
print("本教程基于Paddle的版本号为:"+paddle.__version__)

2.准备数据

#导入数据集Compose的作用是将用于数据集预处理的接口以列表的方式进行组合。
#导入数据集Normalize的作用是图像归一化处理,支持两种方式: 1. 用统一的均值和标准差值对图像的每个通道进行归一化处理; 2. 对每个通道指定不同的均值和标准差值进行归一化处理。
from paddle.vision.transforms import Compose, Normalize
transform = Compose([Normalize(mean=[127.5],std=[127.5],data_format='CHW')])
# 使用transform对数据集做归一化
print('下载并加载训练数据')
train_dataset = paddle.vision.datasets.MNIST(mode='train', transform=transform)
test_dataset = paddle.vision.datasets.MNIST(mode='test', transform=transform)
print('加载完成')

3.网络配置

以下的代码判断就是定义一个简单的多层感知器,一共有三层,两个大小为100的隐层和一个大小为10的输出层,因为MNIST数据集是手写0到9的灰度图像,类别有10个,所以最后的输出大小是10。最后输出层的激活函数是Softmax,所以最后的输出层相当于一个分类器。加上一个输入层的话,多层感知器的结构是:输入层–>>隐层–>>隐层–>>输出层。

import paddle
# 定义多层感知器 
#动态图定义多层感知器
class multilayer_perceptron(paddle.nn.Layer):
    def __init__(self):
        super(multilayer_perceptron,self).__init__()
        #请在这里补全网络代码
        self.flatten=paddle.nn.Flatten()
        self.linear_1=paddle.nn.Linear(784,512)
        self.linear_2=paddle.nn.Linear(512,10)
        self.relu=paddle.nn.ReLU()
        self.dropout=paddle.nn.Dropout(0,2)

    def forward(self, x):
        #请在这里补全传播过程的代码
        y = self.flatten(x)
        y = self.linear_1(y)
        y = self.relu(y)
        y = self.dropout(y)
        y = self.linear_2(y)
        return y
#请在这里定义卷积网络的代码
#注意:定义完成卷积的代码后,后面的代码是需要修改的!
net_cls = multilayer_perceptron()
from paddle.metric import Accuracy

# 用Model封装模型
model = paddle.Model(net_cls)   

# 定义损失函数
optim = paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters())

# 配置模型
model.prepare(optim,paddle.nn.CrossEntropyLoss(),Accuracy())

4.训练模型

# 训练保存并验证模型
model.fit(train_dataset,test_dataset,epochs=2,batch_size=64,save_dir='multilayer_perceptron',verbose=1)

5.用训练好的模型进行预测

#获取测试集的第一个图片
test_data0, test_label_0 = test_dataset[0][0],test_dataset[0][1]
test_data0 = test_data0.reshape([28,28])
plt.figure(figsize=(2,2))
#展示测试集中的第一个图片
print(plt.imshow(test_data0, cmap=plt.cm.binary))
print('test_data0 的标签为: ' + str(test_label_0))
#模型预测
result = model.predict(test_dataset, batch_size=1)
#打印模型预测的结果
edict(test_dataset, batch_size=1)
#打印模型预测的结果
print('test_data0 预测的数值为:%d' % np.argsort(result[0][0])[0][-1])
    AxesImage(18,18;111.6x108.72)
    test_data0 的标签为: [7]
    Predict begin...
    step 10000/10000 [==============================] - 1ms/step        
    Predict samples: 10000
    test_data0 预测的数值为:7

在这里插入图片描述

第三课作业-1

(1)能够跑通项目得到结果;
(2)通过修改模型、数据增强等方法,使得模型在测试数据集上的准确度达到85%及以上。

1.定义数据读取和数据预处理函数

#自定义的数据预处理函数,输入原始图像,输出处理后的图像,可以借用paddle.vision.transforms的数据处理功能
def preprocess(img, is_val):
   if is_val:
       transform = Compose([
           Resize(size=(224, 224)), #把数据长宽像素调成224*224
           Normalize(mean=[127.5, 127.5, 127.5], std=[127.5, 127.5, 127.5], data_format='HWC'), #标准化
           Transpose(), #原始数据形状维度是HWC格式,经过Transpose,转换为CHW格式
           ])
   else:
       transform = Compose([
           Resize(size=(224, 224)), #把数据长宽像素调成224*224
           #ColorJitter(0.4, 0.4, 0.4, 0.4),
           RandomHorizontalFlip(),
           RandomRotation(90),
           Normalize(mean=[127.5, 127.5, 127.5], std=[127.5, 127.5, 127.5], data_format='HWC'), #标准化
           Transpose(), #原始数据形状维度是HWC格式,经过Transpose,转换为CHW格式
           ])
   img = transform(img).astype("float32")
   return img

#自定义数据读取器
class Reader(Dataset):
   def __init__(self, data, is_val=False):
       super(Reader, self).__init__()
       self.is_val = is_val
       #在初始化阶段,把数据集划分训练集和测试集。由于在读取前样本已经被打乱顺序,取20%的样本作为测试集,80%的样本作为训练集。
       self.samples = data[-int(len(data)*0.2):] if self.is_val else data[:-int(len(data)*0.2)]

   def __getitem__(self, idx):
       #处理图像
       img_path = self.samples[idx][0] #得到某样本的路径
       img = Image.open(img_path)
       if img.mode != 'RGB':
           img = img.convert('RGB')
       img = preprocess(img, self.is_val) #数据预处理--这里仅包括简单数据预处理,没有用到数据增强

       #处理标签
       label = self.samples[idx][1] #得到某样本的标签
       label = np.array([label], dtype="int64") #把标签数据类型转成int64
       return img, label

   def __len__(self):
       #返回每个Epoch中图片数量
       return len(self.samples)

#生成训练数据集实例
train_dataset = Reader(data_list, is_val=False)

#生成测试数据集实例
eval_dataset = Reader(data_list, is_val=True)

2.建立模型

#定义模型
class MyNet(paddle.nn.Layer):
   def __init__(self):
       super(MyNet,self).__init__()
       self.layer=paddle.vision.models.resnet101(num_classes=20, pretrained=True)
       #self.fc = paddle.nn.Linear(1000, 20)
   #网络的前向计算过程
   def forward(self,x):
       x=self.layer(x)
       #x=self.fc(x)
       return x

3.应用高阶API训练模型

total_images = len(train_dataset)
batch_size = 64
EPOCHS = 75

#定义输入
input_define = paddle.static.InputSpec(shape=[-1,3,224,224], dtype="float32", name="img")
label_define = paddle.static.InputSpec(shape=[-1,1], dtype="int64", name="label")

#实例化网络对象并定义优化器等训练逻辑
model = MyNet()
model = paddle.Model(model,inputs=input_define,labels=label_define) #用Paddle.Model()对模型进行封装
optimizer = paddle.optimizer.Adam(learning_rate=0.00003, parameters=model.parameters(), weight_decay=5e-4)
#上述优化器中的学习率(learning_rate)参数很重要。要是训练过程中得到的准确率呈震荡状态,忽大忽小,可以试试进一步把学习率调低。

model.prepare(optimizer=optimizer, #指定优化器
              loss=paddle.nn.CrossEntropyLoss(), #指定损失函数
              metrics=paddle.metric.Accuracy()) #指定评估方法

#用于visualdl可视化
visualdl = paddle.callbacks.VisualDL(log_dir='visualdl_log')
#早停机制,在eval_acc不增大10个epoch时停止训练并保存最佳模型
early_stop = paddle.callbacks.EarlyStopping(
                                            'acc',
                                            mode='max',
                                            patience=10,
                                            verbose=1,
                                            min_delta=0,
                                            baseline=None,
                                            save_best_model=True)

model.fit(train_data=train_dataset,     #训练数据集
          eval_data=eval_dataset,         #测试数据集
          batch_size=batch_size,                  #一个批次的样本数量
          epochs=EPOCHS,                      #迭代轮次
          save_dir="/home/aistudio/res101", #把模型参数、优化器参数保存至自定义的文件夹
          save_freq=10,                    #设定每隔多少个epoch保存模型参数及优化器参数
          shuffle=True,
          verbose=1,
          callbacks=[visualdl, early_stop]
)

4.加载最佳模型并用检验模型质量

#加载best模型
model.load('./res101/best_model.pdparams')
result = model.evaluate(eval_dataset, verbose=1)

print(result)
Eval begin...
The loss value printed in the log is the current batch, and the metric is the average value of previous step.
step 373/373 [==============================] - loss: 5.6848 - acc: 0.9035 - 56ms/step        
Eval samples: 373
{'loss': [5.6848283], 'acc': 0.903485254691689}

5.应用已经训练好的模型进行预测

class InferDataset(Dataset):
  def __init__(self, img_path=None):
      """
      数据读取Reader(推理)
      :param img_path: 推理单张图片
      """
      super().__init__()
      if img_path:
          self.img_paths = [img_path]
      else:
          raise Exception("请指定需要预测对应图片路径")

  def __getitem__(self, index):
      # 获取图像路径
      img_path = self.img_paths[index]
      # 使用Pillow来读取图像数据并转成Numpy格式
      img = Image.open(img_path)
      if img.mode != 'RGB': 
          img = img.convert('RGB') 
      img = preprocess(img, True) #数据预处理--这里仅包括简单数据预处理,没有用到数据增强
      return img

  def __len__(self):
      return len(self.img_paths)

#实例化推理模型
model = paddle.Model(MyNet(),inputs=input_define)

#读取刚刚训练好的参数
model.load('./res101/best_model.pdparams')

#准备模型
model.prepare()

#得到待预测数据集中每个图像的读取路径
infer_list=[]
with open("/home/aistudio/data/testpath.txt") as file_pred:
  for line in file_pred:
      infer_list.append("/home/aistudio/data/"+line.strip())

#模型预测结果通常是个数,需要获得其对应的文字标签。这里需要建立一个字典。
def get_label_dict2():
  label_list2=[]
  with open("/home/aistudio/data/species.txt") as filess:
      for line in filess:
          a,b = line.strip("\n").split(" ")
          label_list2.append([int(a)-1, b])
  label_dic2 = dict(label_list2)
  return label_dic2

label_dict2 = get_label_dict2()
#print(label_dict2)

#利用训练好的模型进行预测
results=[]
for infer_path in infer_list:
  infer_data = InferDataset(infer_path)
  result = model.predict(test_data=infer_data)[0] #关键代码,实现预测功能
  result = paddle.to_tensor(result)
  result = np.argmax(result.numpy()) #获得最大值所在的序号
  results.append("{}".format(label_dict2[result])) #查找该序号所对应的标签名字

#把结果保存起来
with open("work/result.txt", "w") as f:
  for r in results:
result = paddle.to_tensor(result)
  result = np.argmax(result.numpy()) #获得最大值所在的序号
  results.append("{}".format(label_dict2[result])) #查找该序号所对应的标签名字

#把结果保存起来
with open("work/result.txt", "w") as f:
  for r in results:
      f.write("{}\n".format(r))

第三课作业-2

(1)能够跑通项目得到结果;
(2)通过修改模型、数据增强等方法,使得模型在测试数据集上的准确度达到85%及以上。

1.数据预处理和数据增强

   对数据进行归一化处理;
   对原有数据进行图像翻转、图像旋转操作以增加训练数据集。
 # 定义数据预处理
data_transforms = T.Compose([
    T.Resize(size=(224, 224)),
    T.RandomVerticalFlip(224),
    T.RandomHorizontalFlip(224),
    T.Transpose(),    # HWC -> CHW
    T.Normalize(
        mean=[0, 0, 0],        # 归一化
        std=[225, 225, 225],
        to_rgb=True)    
])

2.配置模型与优化器

import paddle
from paddle.vision import models

#模型封装
model_res = models.mobilenet_v2(num_classes=4,pretrained=True)
model = paddle.Model(model_res)

#定义优化器
optim = paddle.optimizer.Adam(learning_rate=0.0001, parameters=model.parameters(),weight_decay=0.0001)

#配置模型
model.prepare(
    optim,
    paddle.nn.CrossEntropyLoss(soft_label=True),
    Accuracy()
    )

3.训练模型

#模型训练与评估
model.fit(train_loader,
        val_loader,
        log_freq=1,
        epochs=10,
        # callbacks=Callbk(write=write, iters=iters),
        verbose=1,
        )
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值