TensorFlow实现kaggle数据集图像分类Ⅱ——tfrecord数据格式制作,展示,与训练一体综合

开篇说明

在第一篇叙述了 TensorFlow实现kaggle数据集图像分类Ⅰ——tfrecord数据格式掌握,由于CSDN不能支持 ipynb 文件,所以我将详细的过程上传至CSDN下载专区,作为开源爱好者,上一篇以及这一篇的代码我会在完成这个项目后一定会将所有的代码上传 GitHub,当然土豪玩家可以自行下载

特别鸣谢

特别鸣谢广大的 CSDN 开发者们的博客对 TensorFlow 函数的讲解
特别鸣谢大量用户的开源精神
特别鸣谢 Youtube kevin28 从图片数据训练的教程对本次使用 tfrecord 与部分功能延申拾得头绪

环境需求与数据集准备

一、数据集获取

kaggle 数据集可以使用 kaggle 令牌进行下载,当然也可以直接通过文件的方式下载,这次选择的是使用比较广泛的 cats_vs_dogs 数据集
数据集

1.获取方式一

cats_vs_dogs 官网直接点击 Download All 下载按钮即可下载
数据集

1.获取方式二

通过kaggle的API令牌进行获取,这是官方以及我自己比较推荐的方式,当然你需要申请并拥有 kaggle 账号,这次的演示以 Google Colab 环境为基础,colab 的基础使用参考 NO.4 Tensorflow在win10下实现object detection,在命令行输入如下(由于 colab 已内置很多模块,我将必要的模块安装也一并写出,方便在自己的 Linux 或 Windows 系统下部署)

# 环境安装
!pip install kaggle
# 创建文件夹
!mkdir .kaggle

下载自己的 API Token,进入自己的 Profile 页面,点击下方的 Create New API Token,会自动下载 kaggle.json 文件,打开里面有一行类似如下的数据,分别对应你的用户名 username 与 加密钥匙 key

{"username":"XXXX","key":"xxxxxxxxxxxxxxxxxxxxxxxxx"}
# 导入 API Token,token 为上述 kaggle.json 文件内容,创建一个 kaggle.json 文件
import json
token = {"username":"XXXX","key":"xxxxxxxxxxxxxxxxxxxxxxxxx"}
with open('/content/.kaggle/kaggle.json', 'w') as file:
    json.dump(token, file)
# 让 kaggle.json 赋予更高的权限
!chmod 600 /content/.kaggle/kaggle.json
# 复制到系统目录
!mkdir ~/.kaggle
!cp /content/.kaggle/kaggle.json ~/.kaggle/kaggle.json
# 设置下载的文件夹路径
!kaggle config set -n path -v /content/drive/My\ Drive/cats_and_dogs

下载时需要复制数据集的 API,在页面下方复制即可
粘贴 API

# 粘贴命令并顺便指明存储路径
!kaggle competitions download -c dogs-vs-cats -p /content/drive/My\ Drive/cats_and_dogs
# 进入数据集文件目录
cd /content/drive/My\ Drive/cats_and_dogs
# 文件解压
!unzip train.zip
# 文件解压
!unzip test1.zip

二 jupyter 环境编写

编写环境使用的是 python 的 jupyter-notebook,TensorFlow-GPU 1.15.2,在此篇 Win10系统下从tensorflow源码编译tensorflow-gpu 1.15 有详细的编译步骤,如何从源码编译最适配自己电脑的 TensorFlow-GPU 版本,在 27th March,Google Colab 默认使用 TensorFlow2.x 版本,我们使用魔法函数,选择 Tensorflow1.x 版本即可

%tensorflow_version 1.x
import tensorflow as tf
print(tf.__version__)

本次教程同时支持本地 Windows,Linux系统

数据预处理与 tfrecord 生成与可视化

一、数据尺寸统一化

本次提供的 resize.py 可以将批量数据进行尺寸统一化,本次数据均采用 [224, 224, 3]尺寸,代码中文件夹根据需求更改
resize.py

import os
from PIL import Image

 
filename = os.listdir("./data/train/")
base_dir = "./data/train/"
new_dir  = "./data/train1/"
size_m = 224
size_n = 224

i = 0
for img in filename:
    i += 1
    image = Image.open(base_dir + img)
    image_size = image.resize((size_m, size_n),Image.ANTIALIAS)
    image_size.save(new_dir+ img)
    if i%500 == 0:
        print('INFO:{} has been dealt')

最后得到大小统一的图片
图片

二、模块导入

先导入本次需要的所有模块

import os
import pandas as pd
from sklearn.utils import shuffle
from matplotlib import pyplot as plt
%matplotlib inline
import tensorflow as tf
from PIL import Image
import numpy as np
import io
import math

三、制作 tfrecord

1.制作 CSV 文件

将图片与标签对应,制作成 CSV 文件,进行打乱,确保输入数据的随机性,cat:0,dog:1,进行打标签

data_dir = './data/train1'
frame_list = []
for filename in os.listdir(data_dir):
    subset_list = []
    class_name = filename.split('.')[0]
    if class_name == 'cat':
        class_int = 0
    else:
        class_int = 1
    subset_list = [filename, class_int]
    frame_list.append(subset_list)
name = ['animal', 'class']
form =pd.DataFrame(columns=name, data=frame_list)
data = shuffle(form)
data.to_csv('./data/data1.csv', encoding='gbk', index=None)

生成的 CSV 文件如下
csv

2.CSV 文件可视化

df_data = pd.read_csv('./data/data1.csv')
df_data

4.tfrecord 文件生成

我们使用原始数据生成 tfrecord,如果使用 resize 数据可以注释

img= img.resize((224,224))

从 CSV 文件中提取文件名与标签,序列化生成 tfrecord

cwd='./data/train/'

writer= tf.python_io.TFRecordWriter('./data/' + 'dog_vs_cat.tfrecords')
for i in range(len(df_data)):
    label = df_data.iloc[i,:][1]
    img_path = cwd + df_data.iloc[i,:][0]
    img=Image.open(img_path)
    
    img= img.resize((224,224))
    
    img_raw=img.tobytes()
    example = tf.train.Example(features=tf.train.Features(feature={
        "label": tf.train.Feature(int64_list=tf.train.Int64List(value=[label])),
        "img_raw": tf.train.Feature(bytes_list=tf.train.BytesList(value=[img_raw]))
    }))
    writer.write(example.SerializeToString())
    if i % 500 == 0:
        print('{} pictures have been dealt'.format(i))
writer.close()

由于图象是 jpeg 格式,生成的 tfrecord 文件较大,生成较小的 tfrecord 一定基础上会损坏图像质量,后期我会上手如何制作较小的 tfrecord 文件

5.tfrecord 可视化

cwd='./data/'
animal_dict = {0: 'cat', 1:'dog'}
filename_queue = tf.train.string_input_producer([cwd + 'dog_vs_cat.tfrecords'])
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
features = tf.parse_single_example(serialized_example,
                                   features={
                                       'label': tf.FixedLenFeature([], tf.int64),
                                       'img_raw' : tf.FixedLenFeature([], tf.string),
                                   })
image = tf.decode_raw(features['img_raw'], tf.uint8)
image = tf.reshape(image, [224, 224, 3])
label = tf.cast(features['label'], tf.int32)


with tf.Session() as sess:
    num = 1
    fig = plt.gcf()
    fig.set_size_inches(20, 30)
    init_op = tf.initialize_all_variables()
    sess.run(init_op)
    coord=tf.train.Coordinator()
    threads= tf.train.start_queue_runners(coord=coord)
    for i in range(18):
        example_image, example_label = sess.run([image,label])
        img=Image.fromarray(example_image, 'RGB')
        ax = plt.subplot(math.ceil(18/3), 3, num)
        ax.imshow(img)
        title = animal_dict[example_label]
        num += 1
        ax.set_title(title, fontsize=20)
        
        # img.save(cwd+str(i)+'_''Label_'+str(l)+'.jpg')
        
    coord.request_stop()
    coord.join(threads)

可视化
习惯性在每次运行网络时,将网络重置

tf.reset_default_graph()

6.tfrecord 解码为 batch

def read_and_decode(tfrecords_file, batch_size, capacity):
    filename_queue = tf.train.string_input_producer([tfrecords_file])  
    reader = tf.TFRecordReader()
    _, serialized_example = reader.read(filename_queue)
    img_features = tf.parse_single_example(serialized_example,
                                            features={
                                                   'label': tf.FixedLenFeature([], tf.int64),
                                                   'img_raw': tf.FixedLenFeature([], tf.string),
                                            })
    image = tf.decode_raw(img_features['img_raw'], tf.uint8)
    label = tf.cast(img_features['label'], tf.int32)
    image = tf.reshape(image, [224, 224,3])
    image = tf.image.per_image_standardization(image)
    image_batch, label_batch = tf.train.batch([image, label],                                       
                                              batch_size= batch_size,
                                                    num_threads= 64,
                                                    capacity = capacity)
    image_batch =  tf.cast(image_batch,dtype=tf.float32)
    label_batch = tf.reshape(label_batch, [batch_size])

    return image_batch, label_batch

开始训练

一、构建网络

网络结构为:卷积→池化→卷积→池化→全连接层→全连接层

def inference(images, batch_size, n_classes):   
    with tf.variable_scope('conv1') as scope:
        weights = tf.get_variable('weights', 
                                  shape=[3,3,3, 16],
                                  dtype=tf.float32, 
                                  initializer=tf.truncated_normal_initializer(stddev=0.1,dtype=tf.float32))
        biases = tf.get_variable('biases', 
                                 shape=[16],
                                 dtype=tf.float32,
                                 initializer=tf.constant_initializer(0.1))
        conv = tf.nn.conv2d(images, weights, strides=[1,1,1,1], padding='SAME')
        pre_activation = tf.nn.bias_add(conv, biases)
        conv1 = tf.nn.relu(pre_activation, name= scope.name)
    
    #pool1 and norm1   
    with tf.variable_scope('pooling1_lrn') as scope:
        pool1 = tf.nn.max_pool(conv1, ksize=[1,3,3,1],strides=[1,2,2,1],
                               padding='SAME', name='pooling1')
        norm1 = tf.nn.lrn(pool1, depth_radius=4, bias=1.0, alpha=0.001/9.0,
                          beta=0.75,name='norm1')
    
    #conv2
    with tf.variable_scope('conv2') as scope:
        weights = tf.get_variable('weights',
                                  shape=[3,3,16,16],
                                  dtype=tf.float32,
                                  initializer=tf.truncated_normal_initializer(stddev=0.1,dtype=tf.float32))
        biases = tf.get_variable('biases',
                                 shape=[16], 
                                 dtype=tf.float32,
                                 initializer=tf.constant_initializer(0.1))
        conv = tf.nn.conv2d(norm1, weights, strides=[1,1,1,1],padding='SAME')
        pre_activation = tf.nn.bias_add(conv, biases)
        conv2 = tf.nn.relu(pre_activation, name='conv2')
    
    
    #pool2 and norm2
    with tf.variable_scope('pooling2_lrn') as scope:
        norm2 = tf.nn.lrn(conv2, depth_radius=4, bias=1.0, alpha=0.001/9.0,
                          beta=0.75,name='norm2')
        pool2 = tf.nn.max_pool(norm2, ksize=[1,3,3,1], strides=[1,1,1,1],
                               padding='SAME',name='pooling2')
    
    
    #local3
    with tf.variable_scope('local3') as scope:
        reshape = tf.reshape(pool2, shape=[batch_size, -1])
        dim = reshape.get_shape()[1].value
        weights = tf.get_variable('weights',
                                  shape=[dim,128],
                                  dtype=tf.float32,
                                  initializer=tf.truncated_normal_initializer(stddev=0.005,dtype=tf.float32))
        biases = tf.get_variable('biases',
                                 shape=[128],
                                 dtype=tf.float32, 
                                 initializer=tf.constant_initializer(0.1))
        local3 = tf.nn.relu(tf.matmul(reshape, weights) + biases, name=scope.name)    
    
    #local4
    with tf.variable_scope('local4') as scope:
        weights = tf.get_variable('weights',
                                  shape=[128,128],
                                  dtype=tf.float32, 
                                  initializer=tf.truncated_normal_initializer(stddev=0.005,dtype=tf.float32))
        biases = tf.get_variable('biases',
                                 shape=[128],
                                 dtype=tf.float32,
                                 initializer=tf.constant_initializer(0.1))
        local4 = tf.nn.relu(tf.matmul(local3, weights) + biases, name='local4')
     
        
    # softmax
    with tf.variable_scope('softmax_linear') as scope:
        weights = tf.get_variable('softmax_linear',
                                  shape=[128, n_classes],
                                  dtype=tf.float32,
                                  initializer=tf.truncated_normal_initializer(stddev=0.005,dtype=tf.float32))
        biases = tf.get_variable('biases', 
                                 shape=[n_classes],
                                 dtype=tf.float32, 
                                 initializer=tf.constant_initializer(0.1))
        softmax_linear = tf.add(tf.matmul(local4, weights), biases, name='softmax_linear')
    
    return softmax_linear

二、定义损失函数,准确率等

def losses(logits, labels):
    with tf.variable_scope('loss') as scope:
        cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits\
                        (logits=logits, labels=labels, name='xentropy_per_example')
        loss = tf.reduce_mean(cross_entropy, name='loss')
        tf.summary.scalar(scope.name+'/loss', loss)
    return loss


def trainning(loss, learning_rate):
    with tf.name_scope('optimizer'):
        optimizer = tf.train.AdamOptimizer(learning_rate= learning_rate)
        global_step = tf.Variable(0, name='global_step', trainable=False)
        train_op = optimizer.minimize(loss, global_step= global_step)
    return train_op


def evaluation(logits, labels):
    with tf.variable_scope('accuracy') as scope:
        correct = tf.nn.in_top_k(logits, labels, 1)
        correct = tf.cast(correct, tf.float16)
        accuracy = tf.reduce_mean(correct)
        tf.summary.scalar(scope.name+'/accuracy', accuracy)
    return accuracy

三、开始训练

N_CLASSES = 2
IMG_W = 224
IMG_H = 224
BATCH_SIZE = 32
CAPACITY = 2000
MAX_STEP = 20000 
learning_rate = 0.0001


def run_training():
    
    tfrecords_file = './data/dog_vs_cat.tfrecords'
    logs_train_dir = './training' 
    train_batch, train_label_batch = read_and_decode(tfrecords_file, batch_size=BATCH_SIZE, capacity=CAPACITY)
    
    
    train_logits = inference(train_batch, BATCH_SIZE, N_CLASSES)
    train_loss = losses(train_logits, train_label_batch)        
    train_op = trainning(train_loss, learning_rate)
    train__acc = evaluation(train_logits, train_label_batch)
       
    summary_op = tf.summary.merge_all()
    sess = tf.Session()
    train_writer = tf.summary.FileWriter(logs_train_dir, sess.graph)
    saver = tf.train.Saver()
    
    sess.run(tf.global_variables_initializer())
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    
    try:
        for step in np.arange(MAX_STEP):
            if coord.should_stop():
                    break
            _, tra_loss, tra_acc = sess.run([train_op, train_loss, train__acc])
               
            if step % 50 == 0:
                print('Step %d, train loss = %.2f, train accuracy = %.2f%%' %(step, tra_loss, tra_acc*100.0))
                summary_str = sess.run(summary_op)
                train_writer.add_summary(summary_str, step)
            
            if step % 2000 == 0 or step == MAX_STEP:
                checkpoint_path = os.path.join(logs_train_dir, 'model.ckpt')
                saver.save(sess, checkpoint_path, global_step=step)
                
    except tf.errors.OutOfRangeError:
        print('Done training -- epoch limit reached')
    finally:
        coord.request_stop()
        
    coord.join(threads)
    sess.close()
run_training()

训练

四、训练可视化

可以进入训练的日志文件夹,打开 tensorboard 进行查看,例如进入 training 文件夹,输入

tensorboard --logdir .

可以看到准确率 accuracy 与 损失值loss图

开始验证

一、验证一张图

1.定义验证一张时的数据获取函数

def get_one_batch(image,  image_W, image_H, batch_size, capacity,label = [10]):

    image = tf.cast(image, tf.string)
    label = tf.cast(label, tf.int32)

    # make an input queue
    input_queue = tf.train.slice_input_producer([image, label], shuffle=True)
    
    label = input_queue[1]
    image_contents = tf.read_file(input_queue[0])
    image = tf.image.decode_jpeg(image_contents, channels=3)    
    image = tf.image.resize_image_with_crop_or_pad(image, image_W, image_H)
    image = tf.image.per_image_standardization(image)
    
    image_batch, label_batch = tf.train.batch([image, label],
                                                batch_size= batch_size,
                                                num_threads= 64, 
                                                capacity = capacity)

    
    label_batch = tf.reshape(label_batch, [batch_size])
    image_batch = tf.cast(image_batch, tf.float32)
    
    return image_batch

2.创建 validation 验证集文件夹

validation 里面全是统一大小的 [224,224,3] 图片
文件

3.验证一张图片

IMG_W = 224
IMG_H = 224
CAPACITY = 1


def evaluate_one_image():
    tf.reset_default_graph()
    
    N_CLASSES = 2
    filename = './data/validation/18.jpg'
    img = Image.open(filename)

    plt.imshow(img)
    test = [filename]
    BATCH_SIZE = 1
    test_batch = get_one_batch(test,
                              IMG_W,
                              IMG_H,
                              BATCH_SIZE, 
                              CAPACITY)

    logits = inference(test_batch, BATCH_SIZE, N_CLASSES)
    
    logs_train_dir = './training/'
    saver = tf.train.Saver()
        
    with tf.Session() as sess:
        print("Reading checkpoints...")
        ckpt = tf.train.get_checkpoint_state(logs_train_dir)
        if ckpt and ckpt.model_checkpoint_path:
            global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
            saver.restore(sess, ckpt.model_checkpoint_path)
            print('Loading success, global_step is %s' % global_step)
        else:
            print('No checkpoint file found')
        
        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess, coord=coord)
        pred = sess.run(tf.nn.softmax(logits))
        classify = pred.argmax()
        if classify == 0:
            print('This is a cat with possibility %.6f' %pred[:, 0])
        else:
             print('This is a dog with possibility %.6f' %pred[:, 1])
        coord.request_stop()
        coord.join(threads)
evaluate_one_image()

图

二、批量验证

1.定义验证一个批次时的数据获取函数

def get_files(file_dir):

    cats = []
    label_cats = []
    dogs = []
    label_dogs = []
    for file in os.listdir(file_dir):
        name = file.split(sep='.')
        if name[0]=='cat':
            cats.append(file_dir + file)
            label_cats.append(0)
        else:
            dogs.append(file_dir + file)
            label_dogs.append(1)
    print('There are %d cats\nThere are %d dogs' %(len(cats), len(dogs)))
    
    image_list = np.hstack((cats, dogs))
    label_list = np.hstack((label_cats, label_dogs))
    
    temp = np.array([image_list, label_list])
    temp = temp.transpose()
    np.random.shuffle(temp)
    
    image_list = list(temp[:, 0])
    label_list = list(temp[:, 1])
    label_list = [int(i) for i in label_list]
    
    
    return image_list, label_list



def get_batch(image, label, image_W, image_H, batch_size, capacity):
    image = tf.cast(image, tf.string)
    label = tf.cast(label, tf.int32)

    # make an input queue
    input_queue = tf.train.slice_input_producer([image, label])
    
    label = input_queue[1]
    image_contents = tf.read_file(input_queue[0])
    image = tf.image.decode_jpeg(image_contents, channels=3)
    
    image = tf.image.resize_image_with_crop_or_pad(image, image_W, image_H)

    image = tf.image.per_image_standardization(image)
    
    image_batch, label_batch = tf.train.batch([image, label],
                                                batch_size= batch_size,
                                                num_threads= 64, 
                                                capacity = capacity)

    
    label_batch = tf.reshape(label_batch, [batch_size])
    image_batch = tf.cast(image_batch, tf.float32)
    
    return image_batch, label_batch

2.创建 test 文件夹

明明与训练集相同,目的是为了获取标签,让其与预测标签对比,我的 test 文件夹下有 500 张图片,猫 250, 狗 250
文件

3.批量验证

IMG_W = 224
IMG_H = 224
CAPACITY = 64


def evaluate_all_image():
    
    tf.reset_default_graph()
    
    test_dir = './data/test/'
    N_CLASSES = 2
    test, test_label = get_files(test_dir)
    BATCH_SIZE = len(test)
    print('There are %d test images totally..' % BATCH_SIZE)
    test_batch, test_label_batch = get_batch(test,
                                                          test_label,
                                                          IMG_W,
                                                          IMG_H,
                                                          BATCH_SIZE, 
                                                          CAPACITY)

    logits = inference(test_batch, BATCH_SIZE, N_CLASSES)
    testloss = losses(logits, test_label_batch) 
    testacc = evaluation(logits, test_label_batch)
    
    logs_train_dir = './training/'
    saver = tf.train.Saver()
        
    with tf.Session() as sess:
        print("Reading checkpoints...")
        ckpt = tf.train.get_checkpoint_state(logs_train_dir)
        if ckpt and ckpt.model_checkpoint_path:
            global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
            saver.restore(sess, ckpt.model_checkpoint_path)
            print('Loading success, global_step is %s' % global_step)
        else:
            print('No checkpoint file found')      
        coord = tf.train.Coordinator()
        threads = tf.train.start_queue_runners(sess=sess, coord=coord)
        test_loss,test_acc = sess.run([testloss,testacc])
        print('The model\'s loss is %.2f' %test_loss)
        correct = int(BATCH_SIZE*test_acc)
        print('Correct : %d' % correct)
        print('Wrong : %d' % (BATCH_SIZE - correct))
        print('The accuracy in test images are %.2f%%' %(test_acc*100.0))
        coord.request_stop()
        coord.join(threads)
evaluate_all_image()

文件

三、预测错误图像可视化

1.获取错误评估的图片列表

对 上一步 test 文件夹预测错误的图像揪出来,可视化,看看那些是预测错误的,上一步显示 500 张中有 10 张预测错误,所以后面应该显示的 10 张图片

IMG_W = 224
IMG_H = 224
CAPACITY = 64

check_dir = './data/test/'


def error_detect_found():
    
    error_list = []
    
    N_CLASSES = 2
    BATCH_SIZE = 1
    logs_train_dir = './training/'
    i = 0
    for filename in os.listdir(check_dir):
        tf.reset_default_graph()
        i += 1
        if i %10 == 0:
            print('---------------------------------------')
            print("INFO:{} has been dealt".format(i))
        if filename.split('.')[0] == 'cat':
            class_raw = 0
        else:
            class_raw = 1
        test = [check_dir + filename]     
        test_batch = get_one_batch(test,
                                  IMG_W,
                                  IMG_H,
                                  BATCH_SIZE, 
                                  CAPACITY)

        logits = inference(test_batch, BATCH_SIZE, N_CLASSES)
        saver = tf.train.Saver()

        with tf.Session() as sess:
            print("Reading checkpoints...")
            ckpt = tf.train.get_checkpoint_state(logs_train_dir)
            if ckpt and ckpt.model_checkpoint_path:
                global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
                saver.restore(sess, ckpt.model_checkpoint_path)
                print('Loading success, global_step is %s' % global_step)
            else:
                print('No checkpoint file found')

            coord = tf.train.Coordinator()
            threads = tf.train.start_queue_runners(sess=sess, coord=coord)
            pred = sess.run(tf.nn.softmax(logits))
            classify = pred.argmax()
            if classify != class_raw:
                error_list.append(filename)
            coord.request_stop()
            coord.join(threads)
    return error_list
error_detect_list = error_detect_found()
error_detect_list

t图
最后只有九张图,我也很懵逼,难道又识别正确了一张,还是我遍历的序号设置少了1,还有训练 20000,保存在 18000,我发现是判定条件设置略有失误,反正不是什么大问题,读者自改就完事了

2.错误图像可视化

def image_plt(image_list):
    image_dir = './data/test/'
    num = 1
    fig = plt.gcf()
    fig.set_size_inches(20, 30)
    for i in range(len(image_list)):
        image = Image.open(image_dir + image_list[i])
        ax = plt.subplot(math.ceil(len(image_list)/3), 3, num)
        ax.imshow(image)
        title = image_list[i]
        num += 1
        ax.set_title(title, fontsize=20)
image_plt(error_detect_list)

显示

3.测试已经预测错误的图像

我以 cat.125.jpg 为例,输入单张测试函数,果然测试错误
错误

综述

最终训练效果
loss
到此从零手写图像分类就完成了,对于如何断点续训,我将在后面的章节给出,Notbook 文件下载地址
cats_vs_dogs_tutorial.ipynb

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值