当前位置: 首页 > news >正文

吴恩达深度学习笔记(六)——超参数调试、Batch正则化和程序框架

一、调试处理

给超参数取值:网格中取样点,随机取值,由粗糙到精细的策略。
在这里插入图片描述
为超参数选择合适的范围:随机取值不是在有效范围内随即均匀取值,选择合适的步进值很重要。

比如搜索学习率α,在0.0001到1之间,如果随机均匀取值,则在0.1到1之间应用了90%的资源,在0.0001到0.1之间只有10%的搜索资源。

因此,不使用线性轴,而使用对数轴会更加合理。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
β越接近于1越敏感,需要密集取值。

超参数调试实践:
在这里插入图片描述
照看一个模型,慢慢修改 vs 同时实验多种模型

二、归一化网络的激活函数

归一化激活函数前的z,又利用 γ \gamma γ β \beta β调整为其他平均值和方差。

在这里插入图片描述
隐藏单元值不必全是平均值0和方差1
在这里插入图片描述
三、Batch Norm

在mini-batch上归一化z值,并更新β和γ的参数。
在这里插入图片描述

Batch Norm有效的原因:

1.归一化输入特征,加速学习。不仅对输入值,还有隐藏单元的值。

2.减弱了前层参数的作用与后层参数的作用之间的联系,使得网络每一层可以自己学习,稍微独立于其他层,降低依赖。

3.有轻微的正则化的效果。因为在mini-batch上计算的方差和均值与整个数据集上的相比,有一些小的噪声,但很小,所以是轻微的正则化。类似于dropout,因为给隐藏单元增加了噪音,使得后部单元不过分依赖于任何一个隐藏单元。

在这里插入图片描述

测试时的Batch Norm

在测试时,需要用其他的方式来得到 μ \mu μ σ 2 \sigma^{2} σ2,用指数加权平均来估算。
在这里插入图片描述
四、softmax

此前学过,参考链接。

五、编程作业——手势识别

参考链接

PS:一直就没有学过tensorflow,也不想花时间再安装库,配置各种环境,也不想跟pytorch混淆了,所以不同于参考链接,这里直接用pytorch实现。

代码:

import h5py
import time
import torch
import numpy as np
import torch.nn as nn
import matplotlib.pyplot as plt


# 加载数据集
def load_dataset():
    train_dataset = h5py.File('datasets/train_signs.h5', "r")
    train_set_x_orig = np.array(train_dataset["train_set_x"][:])  # your train set features
    train_set_y_orig = np.array(train_dataset["train_set_y"][:])  # your train set labels

    test_dataset = h5py.File('datasets/test_signs.h5', "r")
    test_set_x_orig = np.array(test_dataset["test_set_x"][:])  # your test set features
    test_set_y_orig = np.array(test_dataset["test_set_y"][:])  # your test set labels

    classes = np.array(test_dataset["list_classes"][:])  # the list of classes

    train_set_y_orig = train_set_y_orig.reshape((train_set_y_orig.shape[0], 1))
    test_set_y_orig = test_set_y_orig.reshape((test_set_y_orig.shape[0], 1))

    return train_set_x_orig, train_set_y_orig, test_set_x_orig, test_set_y_orig, classes

X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_dataset()

print(X_train_orig.shape) # (1080, 64, 64, 3),训练集1080张,图像大小是64*64
print(Y_train_orig.shape) #  (1080, 1)
print(X_test_orig.shape) # (120, 64, 64, 3),测试集120张
print(Y_test_orig.shape)  # (120, 1)
print(classes.shape) # (6,) 一共6种类别,0,1,2,3,4,5

# 查看其中的一张
index = 11
plt.imshow(X_train_orig[index])
plt.show()
print("Y = " + str(np.squeeze(Y_train_orig[index])))

# 处理并归一化数据
X_train_flatten = X_train_orig.reshape(X_train_orig.shape[0],-1) #每一行就是一个样本
X_test_flatten = X_test_orig.reshape(X_test_orig.shape[0],-1)

X_train = X_train_flatten / 255
X_test = X_test_flatten / 255

Y_train = Y_train_orig
Y_test = Y_test_orig

'''
# 转换为独热矩阵
def convert_to_one_hot(Y, C):
    Y = np.eye(C)[Y.reshape(-1)] # 大小为6*6的单位矩阵
    return Y

Y_train = convert_to_one_hot(Y_train_orig, 6)
Y_test = convert_to_one_hot(Y_test_orig, 6)
'''

# 转成Tensor方便后面的训练
X_train = torch.tensor(X_train, dtype=torch.float)
X_test = torch.tensor(X_test, dtype=torch.float)
Y_train = torch.tensor(Y_train, dtype=torch.float)
Y_test = torch.tensor(Y_test, dtype=torch.float)

print(X_train.shape)
print(X_test.shape)
print(Y_train.shape)
print(Y_test.shape)

# 建立模型
num_inputs, num_outputs, num_hiddens_1, num_hiddens_2 = X_train.shape[1], 6, 25, 12

net = nn.Sequential(
    nn.Linear(num_inputs, num_hiddens_1), nn.ReLU(),
    #nn.Dropout(p=0.2),
    nn.Linear(num_hiddens_1, num_hiddens_2), nn.ReLU(),
    #nn.Dropout(p=0.5),
    nn.Linear(num_hiddens_2, num_outputs), nn.Softmax(dim=1))

# 随机初始化模型的权重参数
for params in net.parameters():
    nn.init.normal_(params, mean=0, std=0.01)

# 定义损失函数
loss = nn.CrossEntropyLoss()

# 训练模型
def model(X_train, Y_train, lr=0.0001, batch_size=32, num_epochs=1500, print_loss=True, is_plot=True):


    # 定义优化器
    optimizer = torch.optim.Adam(net.parameters(), lr=lr)

    # 将训练数据的特征和标签组合
    dataset = torch.utils.data.TensorDataset(X_train, Y_train)
    train_iter = torch.utils.data.DataLoader(dataset, batch_size, shuffle=True)

    train_l_list, train_acc_list = [], []
    for epoch in range(num_epochs):

        train_l_sum, train_acc_sum, n = 0.0, 0.0, 0
        for X, y in train_iter:
            y_hat = net(X)
            y = y.squeeze(
                1).long()  # .squeeze()用来将[batch_size,1]降维至[batch_size],.long用来将floatTensor转化为LongTensor,loss函数对类型有要求
            l = loss(y_hat, y).sum()
            # print(y.shape,y_hat.shape)
            # print(l)

            # 梯度清零
            optimizer.zero_grad()

            l.backward()
            optimizer.step()

            train_l_sum += l.item()
            train_acc_sum += (y_hat.argmax(dim=1) == y).sum().item()
            # print(y_hat.argmax(dim=1).shape,y.shape)
            n += y.shape[0]
        train_l_list.append(train_l_sum / n)
        train_acc_list.append(train_acc_sum / n)
        if print_loss and ((epoch + 1) % 100 == 0):
            print('epoch %d, loss %.4f, train acc %.3f' % (epoch + 1, train_l_sum / n, train_acc_sum / n))

    # 画图展示
    if is_plot:
        epochs_list = range(1, num_epochs + 1)

        plt.subplot(211)
        plt.plot(epochs_list, train_acc_list, label='train acc', color='r')

        plt.title('Train acc')
        plt.xlabel('Epochs')
        plt.ylabel('Acc')
        plt.tight_layout()
        plt.legend()

        plt.subplot(212)
        plt.plot(epochs_list, train_l_list, label='train loss', color='b')
        plt.title('Train loss')
        plt.xlabel('Epochs')
        plt.ylabel('Loss')
        plt.tight_layout()
        plt.legend()
        plt.show()

    return train_l_list, train_acc_list

#开始时间
start_time = time.clock()
#开始训练
train_l_list, train_acc_list = model(X_train, Y_train, lr=0.0001, batch_size=32, num_epochs=1500, print_loss=True, is_plot=True)
#结束时间
end_time = time.clock()
#计算时差
print("CPU的执行时间 = " + str(end_time - start_time) + " 秒" )

#计算分类准确率
def evaluate_accuracy(X_test, Y_test, net):

    acc = (net(X_test).argmax(dim=1) == Y_test.squeeze()).sum().item()
    acc = acc / X_test.shape[0]

    return acc

accuracy = evaluate_accuracy(X_test, Y_test, net)
print("测试集的准确率:", accuracy)

输出:
在这里插入图片描述
(话说这张图刚弹出来的时候,我以为是在对我竖中指…)

在这里插入图片描述

(1080, 64, 64, 3)
(1080, 1)
(120, 64, 64, 3)
(120, 1)
(6,)
Y = 1
torch.Size([1080, 12288])
torch.Size([120, 12288])
torch.Size([1080, 1])
torch.Size([120, 1])
epoch 100, loss 0.0489, train acc 0.494
epoch 200, loss 0.0464, train acc 0.584
epoch 300, loss 0.0440, train acc 0.683
epoch 400, loss 0.0416, train acc 0.750
epoch 500, loss 0.0402, train acc 0.791
epoch 600, loss 0.0391, train acc 0.817
epoch 700, loss 0.0381, train acc 0.850
epoch 800, loss 0.0375, train acc 0.864
epoch 900, loss 0.0372, train acc 0.869
epoch 1000, loss 0.0368, train acc 0.877
epoch 1100, loss 0.0367, train acc 0.881
epoch 1200, loss 0.0363, train acc 0.891
epoch 1300, loss 0.0362, train acc 0.894
epoch 1400, loss 0.0361, train acc 0.897
epoch 1500, loss 0.0359, train acc 0.902
CPU的执行时间 = 169.80180710000002 秒
测试集的准确率: 0.7916666666666666

从结果可见,训练集上的准确率能达到90.2%,测试集上有79.17%,跟参考链接的取得的结果差不多,已经是可以识别0-5的手势符号了。

但其中需要注意的是,pytorch中的交叉熵损失函数并不需要你提前将标签转为one-hot编码,自己就可以处理。

参考链接

另外,其CPU执行时间,也与你什么时候叉掉弹出来的结果图有关,所以为了精确确定时间,可以将损失图和准确率图设置为不予展示。

而且因为没有像之前的作业那样,使用固定的随机化种子初始参数,所以每次运行得到的最终结果,会有细微的差异。

使用自己拍的手势图:

在这里插入图片描述

from skimage.transform import resize

fname = r"D:\PyCharm files\deep learning\吴恩达\L2W3\5.jpg"
image = np.array(plt.imread(fname))
num_px = 64
print(image.shape)


my_image = resize(image,output_shape=(num_px,num_px))  # 修改尺寸为64*64
plt.imshow(my_image)
plt.show()

my_image = my_image.reshape((1, num_px*num_px*3))  # 转换成向量便于预测
my_image = torch.tensor(my_image, dtype=torch.float)
print(my_image.shape)
my_label_y = [5]
pred = net(my_image).detach().numpy()
pred_label = pred.argmax()
if my_label_y == pred_label:
    print("预测正确!这个手势就是{}".format(my_label_y[0]))
else:
    print("预测错误!你的模型认为这是{},但其实这个手势是{}".format(pred_label, my_label_y[0]))

输出:
在这里插入图片描述

(3730, 2982, 3)
torch.Size([1, 12288])
预测错误!你的模型认为这是4,但其实这个手势是5

遇到了以前作业遇到的问题,这个识别不太行。但也懒得做其他的图了

相关文章:

  • 【甄选靶场】Vulnhub百个项目渗透——项目十六:FristiLeaks_1.3(文件上传,py脚本改写,sudo提权,脏牛提权,源码获取)
  • 苹果iPhone手机iOS16如何取消关闭复制粘贴时不停弹出的剪贴板粘贴提示通知弹窗?
  • Android移动应用开发之ImageView、ProgressBar和Notification的一些简单使用
  • SQL经典练习题(openGauss数据库)上
  • CSDN编程竞赛-第六期(下)
  • Spring 静态属性赋值 @value 注入静态属性 @Value注解用法
  • 【零基础学QT】第九章 窗口美化QSS的使用
  • aws codesuit workshop
  • Linux内存管理——段页式访问
  • Hadoop基础学习笔记
  • 微信小程序 - 页面插入添加 Banner 广告超详细教程(支持自定义样式、位置、大小等)及注意事项
  • JavaScript笔记9-节点操作
  • 【YOLOv7】使用 YOLOv7 做目标检测 (使用自己的数据集 + 图解超详细)
  • 【C语言】break 关键字
  • sql窗口函数学习笔记
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • 【RocksDB】TransactionDB源码分析
  • 【笔记】你不知道的JS读书笔记——Promise
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • Flannel解读
  • JavaScript 基本功--面试宝典
  • Javascript基础之Array数组API
  • js写一个简单的选项卡
  • Logstash 参考指南(目录)
  • nodejs调试方法
  • npx命令介绍
  • RxJS 实现摩斯密码(Morse) 【内附脑图】
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 关于springcloud Gateway中的限流
  • 海量大数据大屏分析展示一步到位:DataWorks数据服务+MaxCompute Lightning对接DataV最佳实践...
  • 将 Measurements 和 Units 应用到物理学
  • 紧急通知:《观止-微软》请在经管柜购买!
  • 聊聊sentinel的DegradeSlot
  • 少走弯路,给Java 1~5 年程序员的建议
  • 数据仓库的几种建模方法
  • 说说动画卡顿的解决方案
  • 正则表达式
  • 正则与JS中的正则
  • 转载:[译] 内容加速黑科技趣谈
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • mysql面试题分组并合并列
  • 积累各种好的链接
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • ​configparser --- 配置文件解析器​
  • ‌移动管家手机智能控制汽车系统
  • #define MODIFY_REG(REG, CLEARMASK, SETMASK)
  • #NOIP 2014#Day.2 T3 解方程
  • (2)nginx 安装、启停
  • (23)mysql中mysqldump备份数据库
  • (function(){})()的分步解析
  • (二)十分简易快速 自己训练样本 opencv级联lbp分类器 车牌识别
  • (分布式缓存)Redis持久化
  • (回溯) LeetCode 46. 全排列
  • (一)插入排序
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)