0
5
¥ 35.00
开通会员,立省3.50元, 立即开通
立即购买

你将收获

在linux和windows系统底下构建和管理python虚拟环境

深度学习和Tensorflow中的概念和用法

用OpenCV和Tensorflow自己动手写一整个项目,包括数据收集,训练模型及部署

学会一种开发思维,而不是纯理论知识

适用人群

学生,程序员

课程介绍

在这个课程里面,讲师将会带着同学们一行一行地写代码,同时也对每一行代码它的作用和目的进行讲解,以及在代码调试过程中遇到问题该怎么处理。其次,这个课程不会涉及太多原理性和数学的东西,而是把深度学习看成是一个工具去教会同学们怎么使用,非常适合刚开始接触深度学习和神经网络但不知道该如何下手的同学。最后,这个课程能教会大家一种实际项目的开发思维,适合想要使用深度学习来开发项目的同学。

课程讨论

真的讲的很不错。 虽然项目是一个小项目,看上去比较基础,但是对于真正刚刚入门的我来说,实在是再合适不过了。 网上深度学习讲的项目到处都是什么Mnist、Cifar-10,听都听腻了,而且数据集也是别人搞好的。自己想做一个自己的项目数据集怎么搞都不知道。 这个课程的项目,给出了一个小项目实现的全部过程(包括数据集的准备、模型的训练、训练好的模型的应用),在我看来实在是不可多得的好课程。 虽然就以一个这样的小项目来说,三十多块钱似乎比较多,但是从这个项目对于新手的友好来说,我觉得确实很不错。 【PS:可惜讲师好像没有其他的一些小项目的课程了,说实话也蛮喜欢这个讲师的,希望这个讲师下次还能有一些其他的小项目hhh】

同学笔记

  • qq_44220418 2020-07-01 12:15:25

    来源:部署网络到应用中 查看详情

     

    目录

    一、用训练模型进行预测代码

    二、思路总结

    1、模型的导入

    2、测试图像的输入

    3、根据测试图像进行预测

    三、API总结


     

    一、用训练模型进行预测代码

    import cv2
    import tensorflow as tf
    
    
    with tf.Session() as sess:
        """加载模型"""
        loader = tf.train.import_meta_graph("./model/model.meta")
        loader.restore(sess, './model/model')
    
        """开始识别"""
        capture = cv2.VideoCapture(0)
        while True:
            ret, frame = capture.read()  # 获取一帧
            show_img = frame.copy()  # show_img是原图像frame的拷贝
            crop_img = frame[100:200, 100:200]  # crop_img是在原图像frame上的部分截取
            cv2.rectangle(show_img, (100, 100), (200, 200), (0, 0, 255), 5)  # 在show_img上画出截取部分的框框
            cv2.imshow('frame', show_img)  # 显示图片show_img
            k = cv2.waitKey(1)  # OpenCV延迟1毫秒、同时检测是否有按键被按下(如果有键被按下时,将键值返回给q)
            # 按下Q键退出
            if k == ord('q'):
                break
            # 按下S键进行识别
            elif k == ord('s'):
                out = sess.run("output:0", feed_dict={"data_in:0": [crop_img]})
                res = ['我', '好', '帅'][out[0]]
                print("识别结果:", res)
                cv2.imshow("crop", crop_img)
    
        capture.release()
        cv2.destroyAllWindows()

     

    二、思路总结

    1、模型的导入

    要有一个会话sess,要构建好模型载入器,要将模型文件路径填入,恢复到会话中

    2、测试图像的输入

    和准备数据集时同样的方法,使用cv调用摄像头,框选部分图像,作为输入

    3、根据测试图像进行预测

    在会话sess中运行模型中与输出相应的"name:后缀",同时将测试图像的数据feed给模型中与输入相应的"name:后缀",得到的返回值即为输出结果。

    这里需要注意的是,本质上sess读取的模型中就蕴含了原来训练时神经网络的结构,所以name要和原来训练时神经网络中变量的name相对应

     

    三、API总结

    API

    作用

    使用示例

    tf.train.import_meta_graph

    构建tf会话载入器

    loader = tf.train.import_meta_graph("./model/model.meta")

    *.restore

    将训练好的模型文件加载到会话中

    loader.restore(sess, './model/model')

  • qq_44220418 2020-07-01 11:08:39

    来源:训练神经网络 查看详情

     

    目录

     一、神经网络训练代码

    二、思路总结

    1、数据集图片数据、目标值的导入

    2、目标值转化为one_hot编码

    3、神经网络中样本、目标的输入

    4、神经网络的搭建

    5、损失的计算与优化

    6、批处理的方法

    7、准确率的计算

    8、模型的保存

    三、API总结


     

    一、神经网络训练代码

    import tensorflow as tf
    import cv2
    import glob
    import os
    import numpy as np
    
    
    def data_reader(dataset_path):
        data_list = []
        label_list = []
        for cls_path in glob.glob(os.path.join(dataset_path, '*')):
            for file_name in glob.glob((os.path.join(cls_path, '*'))):
                img = cv2.imread(file_name)
                data_list.append(img)
                label_list.append(int(cls_path[-1]))
        data_np = np.array(data_list)
        label_np = np.array(label_list)
        return data_np, label_np
    
    
    def shuffle_data(data, label):
        idx = np.arange(len(data))
        np.random.shuffle(idx)
        return data[idx, ...], label[idx, ...]
    
    
    def train(data, label):
        data_in = tf.placeholder(tf.float32, [None, 100, 100, 3], name="data_in")  # None实际上指的是batch的大小,batch的大小可以在运行时改变
        label_in = tf.placeholder(tf.float32, [None, 3])  # 准备构造一个one_hot的label,而我们的数据总共有3个类
    
        # 一个小的卷积网络,用来处理图片
        # (如果数据量大,需要构造一个大一点的神经网络,可以在卷积网络部分复制一下,就可以构造一个比较深的神经网络)
        # (但是神经网络并不是越深越好,可能会涉及过拟合、梯度消失等问题)
        # (目前网络参数的取值,主要还是根据数据集特征和大小,还有靠我们的直觉的经验。)
        # (所以神经网络也叫作当代炼金术)
        out = tf.layers.conv2d(data_in, 4, 3, padding='same')  # out形状为[?, 100, 100, 4]
        out = tf.layers.max_pooling2d(out, 2, 2, padding='same')  # out形状为[?, 50, 50, 4]
        out = tf.nn.relu(out)  # out形状为[?, 50, 50, 4]
    
        # 把提取出来的特征压扁成一个一维数组
        out = tf.reshape(out, (-1, int(np.prod(out.get_shape()[1:]))))  # out形状为[?, 10000]
    
        # 送入全连接层
        out = tf.layers.dense(out, 2000, activation=tf.nn.relu)
        # 再加一个全连接层(按理说,我们数据量很少,应该会过拟合,也就数准确率接近100%)
        out = tf.layers.dense(out, 256, activation=tf.nn.relu)
    
        # 得到输出(输出的分类数要和输入的label的分类数一样,不然会报错)
        pred = tf.layers.dense(out, 3)
    
        # 将one_hot变回值0、1、2
        out_label = tf.argmax(pred, 1, name="output")
    
        # 计算交叉熵损失
        loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=label_in, logits=pred))
        # 梯度下降、优化损失
        train_op = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
    
        # 初始化变量的op
        init_op = tf.initialize_all_variables()
    
        # 定义一些参数
        batch_size = 16
    
        # 进行会话
        with tf.Session() as sess:
            sess.run(init_op)
            # 进行多次训练
            for epoch in range(50):
                # (在训练的时候,我们不希望每次取到的数据的顺序都是一样的,这样很容易导致过拟合)
                # (因此我们一般会加一个shuffle,也就是在输入到网络前,把数据顺序打乱)
                datas, labels = shuffle_data(data, label)
                # 准确率统计
                total_loss = 0
                avg_accuracy = 0
                # 按批次训练
                num_batch = len(data) // batch_size
                for batch_idx in range(num_batch):
                    # 计算每个batch开始和结束时候的下标
                    start_idx = batch_idx * batch_size
                    end_idx = (batch_idx + 1) * batch_size
                    # 准备好输入层的数据
                    # (...代表省略后面的形状)
                    feed_dict = {data_in: datas[start_idx: end_idx, ...],
                                 label_in: labels[start_idx: end_idx, ...]}
                    # 计算准确率
                    correct_prediction = tf.equal(out_label, tf.argmax(label_in, 1))
                    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
                    # 进行训练
                    _, loss_out, acc = sess.run([train_op, loss, accuracy], feed_dict=feed_dict)
                    # 准确率统计
                    total_loss += loss_out
                    avg_accuracy += acc
                # 统计每批次准确率
                print("avg_accuracy", avg_accuracy / num_batch)
                # 准确率够高则保存模型
                if avg_accuracy / num_batch > 0.94:
                    saver = tf.train.Saver()
                    saver.save(sess, './model/model')
                    break
    
    
    def dense_to_one_hot(label, num_class):
        num_label = label.shape[0]
        index_offset = np.arange(num_label) * num_class
        label_one_hot = np.zeros((num_label, num_class))
        label_one_hot.flat[index_offset + label.ravel()] = 1
        return label_one_hot
    
    
    if __name__ == '__main__':
        dataset_path = "./dataset"
        data, label = data_reader(dataset_path)
        one_hot_label = dense_to_one_hot(label, 3)
        train(data, one_hot_label)

     

    二、思路总结

    1、数据集图片数据、目标值的导入

    图片数据

    首先,用cv读取图片,将图片一个一个添加到一个list里面去。

    其次,用np(numpy)将图片的列表转化为np数组。

    图片目标值

    首先,由于图片被按照目录分类

    在读取图片时,每读取一张图,就将图片的上级目录的名字作为一个目标值。(这里是0、1、2)

    2、目标值转化为one_hot编码

    步骤如下:

    1. 原本一个样本只有一个目标值

    2. 一共600个样本,目标值总的可能性有3种(某种目标的one_hot编码就只可能是[1, 0, 0]、[0, 1, 0]、[0, 0, 1])

    3. 先生成好一个全零的、形状为(600, 3)的np数组𝐴,准备将值1填入对应标签位置的位置

    4. 准备好每个样本在𝐴展平后的数组𝐵中的one_hot特征下标

    5. 将1填入上一步中展平下标对应在数组𝐴中的位置

    3、神经网络中样本、目标的输入

    可以通过一个占位符来实现,个数的那一维填写None,代表暂时不知道每次训练的样本数量,在实际训练中会根据每批次训练数量加以给定。

    比如,我们这里的样本数为600,每个样本的形状都是(100, 100, 3),也就是总的样本的形状为(600, 100, 100, 3),那么我们样本输入的占位符的形状就应该为(None, 100, 100, 3);同样地,我们one_hot目标值的形状为(600, 3),那么我们样本目标值的占位符形状就应该为(None, 3)

    4、神经网络的搭建

    步骤如下:

    1. 接入一个卷积层(tf.layers.conv2d)

      第一个参数(inputs)为输入数据

      第二个参数(filters)为卷积核的数量

      第三个参数(kernel_size)为卷积核的大小

      (这里因为我们的数据比较简单、类别也少,所以filters取了比较小的值4)

      (如果像是imagenet那种大型数据集一般会取到128或者256那样)

    2. 接入一个池化层(用于减少数据量)(tf.layers.max_pooling2d)

      第一个参数(inputs)为输入

      第二个参数(pool_size)为池化核的大小

      第三个参数(strides)为卷积核的步长

      (这里我们都把pool_size和strides设置为2)

    3. 加上一个激活函数ReLU

    4. 把神经网络的输出拍扁,做成一个一维数组

    5. 添加几个全连接层(tf.layers.dense)

      第一个参数(inputs)为输入

      第二个参数(unit)为输出的维度大小(改变inputs的最后一维),同时也是神经元的个数

      (一开始中间加入的是一层,后来发现一层全连接层训练的效果不怎么好,改成了两层)

    6. 再接入一个全连接层得到输出

      (注意,输出的分类数要和目标label的分类数相同,否则会报错)

    5、损失的计算与优化

    损失计算

    计算交叉熵损失

    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=label_in, logits=pred))

    优化

    使用Adam优化算法

    train_op = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)

    6、批处理的方法

    步骤如下:

    1. 设置每批次的训练数量batch_size、训练的趟数

    2. 每趟训练前件训练用的输入数据随机打乱

    3. 计算好每一趟训练的批次数量,对每一批次用batch_size个样本进行训练

    7、准确率的计算

    步骤如下:

    1. 找到预测值、目标值的每一个样本在one_hot编码中的横向下标

      tf.argmax(pred, 1, name="output")
      tf.argmax(label_in, 1)
    2. 对比预测值、目标值的下标值是否相等,由此得到一个判断对应样本的预测值与目标值是否相等的tf张量

      correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(label_in, 1))
    3. 从上面的比对张量中计算平均值,得到这一批次的准确率

    4. 在一趟训练结束后,将所有批次准确率相加求和,再除以训练批次数量,就得到了这一趟训练的平均准确率

    8、模型的保存

    步骤如下:

    1. 构造一个tf模型存储器

      saver = tf.train.Saver()
    2. 指定会话、模型存储路径

      saver.save(sess, './目录/模型名')

    这里需要注意的是,我们需要为输入数据占位符data_in、预测值out_label增加上各自的name,这是为了之后模型读取的方便

     

    三、API总结

    API

    作用

    使用示例

    glob.glob

    返回某个路径下所有被匹配的文件/目录路径生成的列表

    for cls_path in glob.glob(os.path.join(dataset_path, '*')):

            ......

    np.array

    根据某种数据类型的值生成相应的np数组

    data_np = np.array(data_list)

    np.arange

    按照指定的start、stop、step生成一个指定的np一维等差数组

    index_offset = np.arange(num_label) * num_class

    np.zeros

    按照指定的shape生成元素全为0的np数组

    label_one_hot = np.zeros((num_label, num_class))

    *.flat[???]

    根据数组展平后的下标获取数组元素

    label_one_hot.flat[index_offset + label.ravel()] = 1

    np.random.shuffle

    随机打乱一串数

    np.random.shuffle(idx)

    tf.placeholder

    创建一个tf占位符

    label_in = tf.placeholder(tf.float32, [None, 3])

    tf.Session

    创建一个tf会话

    with tf.Session() as sess:

            ......

    tf.initialize_all_variables

    创建一个tf变量初始化op

    init_op = tf.initialize_all_variables()

    tf.train.Saver

    创建一个tf会话存储器

    saver = tf.train.Saver()

    *.save

    保存会话中的训练模型

    saver.save(sess, './model/model')

    tf.argmax

    找出张量在某一维度上的最大值对应的下标

    out_label = tf.argmax(pred, 1, name="output")

    tf.reduce_mean

    计算平均值

    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    tf.cast

    将某个张量的数据类型进行转换

    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    tf.equal

    按元素比较两个张量,返回相等情况对应的张量

    correct_prediction = tf.equal(out_label, tf.argmax(label_in, 1))

    tf.nn.

    softmax_cross_entropy

    _with_logits_v2

    计算交叉熵损失

    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(labels=label_in, logits=pred))

    tf.layers.conv2d

    构建卷积层

    out = tf.layers.conv2d(data_in, 4, 3, padding='same')

    tf.layers.max_pooling2d

    构建池化层

    out = tf.layers.max_pooling2d(out, 2, 2, padding='same')

    tf.nn.relu

    激活函数ReLU

    out = tf.nn.relu(out)

    tf.layers.dense

    构造全连接层

    out = tf.layers.dense(out, 2000, activation=tf.nn.relu)

     

  • qq_44220418 2020-06-30 20:10:55

    来源:深度学习简介 查看详情

     

    目录

    一、制作数据集代码

    二、思路总结

    1、数据集目录的准备

    2、图片的获取

    3、样本的录入与样本类型的切换

    4、数据集存放的方法

    三、API使用总结


     

    一、制作数据集代码

    import cv2
    import os
    
    """数据集目录准备"""
    dataset_path = "./dataset"  # 数据集目录
    
    # 检验数据集目录是否存在,不存在则创建目录
    if not os.path.exists(dataset_path):
        os.mkdir(dataset_path)
    
    # 在数据集路径下,检测3个类的路径是否存在,不存在则创建目录
    for i in range(3):
        class_path = dataset_path + f"/{i}"
        if not os.path.exists(class_path):
            os.mkdir(class_path)
    
    """图片编号准备"""
    data_counter = 0  # 每一类图片的计数器
    class_number = 0  # 图片类型编号
    
    """摄像头取材准备"""
    capture = cv2.VideoCapture(0)
    while True:
        ret, frame = capture.read()  # 获取一帧
        show_img = frame.copy()  # show_img是原图像frame的拷贝
        crop_img = frame[100:200, 100:200]  # crop_img是在原图像frame上的部分截取
        cv2.rectangle(show_img, (100, 100), (200, 200), (0, 0, 255), 5)  # 在show_img上画出截取部分的框框
        cv2.imshow('frame', show_img)  # 显示图片show_img
        k = cv2.waitKey(1)  # OpenCV延迟1毫秒、同时检测是否有按键被按下(如果有键被按下时,将键值返回给q)
        # 按下Q键退出
        if k == ord('q'):
            break
        # 按下S键保存
        elif k == ord('s'):
            file_name = dataset_path + f"/{class_number}" + "/%03d.jpg" % data_counter  # 记录保存图片的相对路径
            cv2.imwrite(file_name, crop_img)  # 保存图片crop_img
            print(f"保存 图片{data_counter}")  # 打印提示
            data_counter += 1  # 计数器 + 1
        # 按下N键进入下一类样本的录入
        elif k == ord('n'):
            class_number += 1
            data_counter = 0
            print(f"进入第{class_number}类样本的识别")
    
    capture.release()
    cv2.destroyAllWindows()

     

    二、思路总结

    1、数据集目录的准备

    主要靠os来判断文件夹是否存在,不存在将提前创建相应文件夹

    2、图片的获取

    主要靠OpenCV打开摄像头,截取框选区域图片进行保存

    3、样本的录入与样本类型的切换

    主要靠OpenCV获取按键,判别按键信息执行对应指令

    4、数据集存放的方法

    在一个dataset的文件夹中,有三个文件夹【0、1、2】,分别对应三类图片数据【“我”、“好”、“帅”】,每一类图片存放在相应类型的文件夹下,各存储200张,编号均为000.jpg~199.jpg

     

    三、API使用总结

    API

    作用

    使用示例

    os.path.exists

    os判断某个文件/目录是否存在

    dataset_path = "./dataset"

    if not os.path.exists(dataset_path):

            ......

    os.mkdir

    os创建某个目录

    os.mkdir(dataset_path)

    cv2.VideoCapture

    cv获取摄像头资源

    capture = cv2.VideoCapture(0)

    *.read

    cv获取摄像头的一帧

    ret, frame = capture.read()

    *.copy

    cv图片拷贝

    show_img = frame.copy()

    *[???:???, ???:???]

    cv图片截取

    crop_img = frame[100:200, 100:200]

    cv2.rectangle

    cv图片画框

    cv2.rectangle(show_img, (100, 100), (200, 200), (0, 0, 255), 5)

    cv2.imshow

    cv图片展示

    cv2.imshow('frame', show_img)

    cv2.imwrite

    cv图片保存

    cv2.imwrite(file_name, crop_img)

    cv2.waitKey

    cv等待按键

    k = cv2.waitKey(1)

    *.release

    cv释放摄像头资源

    capture.release()

    cv2.destroyAllWindows

    关闭所有cv窗口

    cv2.destroyAllWindows()

    ord

    返回字符对应的ASCII码值

    if k == ord('q'):

            break

没有更多了