TensorFlow下CIFAR10-100数据集的自动下载与处理(附百度网盘地址)及卷积神经网络处理Cifar100程序

一、下载数据集

TensorFlow2.0有常用数据集(mnist、fashion_mnist、cifar10、cifar100的下载接口,下载过后是numpy数据,只需将其转换为TensorFlow即可使用,非常的方便

import  tensorflow as tf
from    tensorflow.keras import layers, optimizers, datasets, Sequential
(x,y), (x_test, y_test) = datasets.cifar100.load_data()		#下载cifar100
(x,y), (x_test, y_test) = datasets.cifar10.load_data()		#下载cifar10

虽然mnist、fashion_mnist可以使用该代码直接下载无需等待。但是这个cifar100和cifar10数据集每个都大于160M,从国外网站下载通常需要2h-12h,中间还有可能停止下载,然后就得重新下载,我下载了一晚上结果还是下载失败。

TensorFlow下CIFAR10-100数据集的自动下载与处理(附百度网盘地址)及卷积神经网络处理Cifar100程序_第1张图片
如果使用浏览器直接从官网下载也很慢,官网地址:http://www.cs.toronto.edu/~kriz/cifar.html
而且断断续续,因此我用了IDM下载器下载了约半个小时(下载器还是很稳定的而且网速也比之前快了十几倍,虽然还是只有90kb/s),百度网盘地址在最后,下载成功后,如何方便的读取和处理呢?
TensorFlow下CIFAR10-100数据集的自动下载与处理(附百度网盘地址)及卷积神经网络处理Cifar100程序_第2张图片

答案就是还用下面几句代码就可以,但是要把下载好的数据集压缩包放到\.keras\datasets路径。(cifar-10下载后名称为cifar-10-python.tar.gz需要重命名为cifar-10-batches-py.tar.gz,cifar-100不用做处理)

import  tensorflow as tf
from    tensorflow.keras import layers, optimizers, datasets, Sequential
(x,y), (x_test, y_test) = datasets.cifar100.load_data()		#下载cifar100
(x,y), (x_test, y_test) = datasets.cifar10.load_data()		#下载cifar10

我发现TensorFlow总是会把下载的压缩包放在C:\Users\17134.keras\datasets路径下,因此只要把下载成功的cifar-100-python.tar.gz复制到该路径下,运行程序时就会自动检测到,然后就不会在自动下载,而是直接开始自动数据处理。当然你前面的路径肯定还我的不一样,但是后面这个路径\.keras\datasets应该是一样的,你可以搜索一下。另外压缩包一定要是从官网下载的原版才行,我使用一个兄弟下载好的,很明显他把原数据包解压后又重新压缩了,压缩格式和原版不一样,导致程序识别不到。
附cifar10-100原版百度网盘地址:
链接:https://pan.baidu.com/s/1fQFeQHKalwc3sny5y5YrCQ
提取码:w4gi

二、卷积神经网络处理Cifar100完整程序

以下是卷积神经网络处理Cifar100的完整程序,使用的13层网络,最终的识别率只有40%,如何提高识别率?初学小菜鸟一枚,欢迎交流探讨

#### lr=0.0001时,最大40%的正确率,最后稳定在39%-40%;lr=0.001时出现了梯度离散现象,loss一直在4.605左右不更新,正确率也一直在1.000%不更新
#### Sequential中有处理reshape的层,但是本代码没有用,如果使用该操作,则本程序使用一张网络就可以了,但是这样可以学到学到东西
#### 如果显卡利用率在70%-80%代表代码优化好,若低于70%,可能cpu部分是瓶颈,将数据加载、处理尽可能放在gpu上,每次batch数也要量力而行,发现当batch为64时gpu利用率明显下降
import  tensorflow as tf
from    tensorflow.keras import layers, optimizers, datasets, Sequential
import  os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
tf.random.set_seed(2345)                                                  #设置图级用于产生随机数的种子,每个seed对应一套预设随机数,所以可以保证每次运行的参数不变
#### 下载数据并转换为tensor
(x_train, y_train), (x_test, y_test) = datasets.cifar100.load_data()      #下载数据,和mnist一样
x_train = tf.convert_to_tensor(x_train, dtype=tf.float32) / 255.          #转换为tensor数据,并映射到0-1
x_test = tf.convert_to_tensor(x_test, dtype=tf.float32) / 255.            #转换为tensor数据,并映射到0-1
y_train = tf.one_hot(tf.convert_to_tensor(tf.squeeze(y_train, axis=1), dtype=tf.int32), depth=100)#注意y有一个多余的维度要去掉,并转换为onehot数据
y_test = tf.convert_to_tensor(tf.squeeze(y_test, axis=1), dtype=tf.int32) #测试集不用转换onehot数据
print(x_train.shape, y_train.shape, x_test.shape, y_test.shape)           #(50000, 32, 32, 3) (50000, 100) (10000, 32, 32, 3) (10000,)
#### batch数据
train_db = tf.data.Dataset.from_tensor_slices((x_train, y_train)).shuffle(10000).batch(128)#打乱数据默认排序,每128个图片打包一下
test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test)).shuffle(10000).batch(64)    #打乱数据默认排序,每64个图片打包一下

conv_layers = [                                                                 #图片宽度和高度慢慢缩小,但每个像素的信息量增大,kernels的个数渐渐增大
    # unit 1
    layers.Conv2D(64, kernel_size=[3,3], padding='same', activation=tf.nn.relu),#输入[b,32,32,3] -> 卷积核[3,3,3,64] -> 输出[b,32,32,64]
    layers.Conv2D(64, kernel_size=[3,3], padding='same', activation=tf.nn.relu),#输入[b,32,32,64] -> 卷积核[3,3,64,64] -> 输出[b,32,32,64]
    layers.MaxPool2D(pool_size=[2, 2],strides=2,padding='same'),                #输入[b,32,32,64] -> b个图片64个输入pooling后[b,16,16,64],步长为2图片长宽减半
    # unit 2
    layers.Conv2D(128, kernel_size=[3,3], padding='same', activation=tf.nn.relu),#输入[b,16,16,64] -> 卷积核[3,3,64,128] -> 输出[b,16,16,128]
    layers.Conv2D(128, kernel_size=[3,3], padding='same', activation=tf.nn.relu),#输入[b,16,16,128] -> 卷积核[3,3,128,128] -> 输出[b,16,16,128]
    layers.MaxPool2D(pool_size=[2, 2],strides=2,padding='same'),                 #输入[b,16,16,128] -> b个图片128个输入pooling后[b,8,8,128]
    # unit 3
    layers.Conv2D(256, kernel_size=[3,3], padding='same', activation=tf.nn.relu),#输入[b,8,8,128] -> 卷积核[3,3,128,256] -> 输出[b,8,8,256]
    layers.Conv2D(256, kernel_size=[3,3], padding='same', activation=tf.nn.relu),#输入[b,8,8,256] -> 卷积核[3,3,256,256] -> 输出[b,8,8,256]
    layers.MaxPool2D(pool_size=[2, 2],strides=2,padding='same'),                 #输入[b,8,8,256] -> b个图片256个输入pooling后[b,4,4,256]
    # unit 4
    layers.Conv2D(512, kernel_size=[3,3], padding='same', activation=tf.nn.relu),#输入[b,4,4,256] -> 卷积核[3,3,256,512] -> 输出[b,4,4,512]
    layers.Conv2D(512, kernel_size=[3,3], padding='same', activation=tf.nn.relu),#输入[b,4,4,512] -> 卷积核[3,3,512,512] -> 输出[b,4,4,512]
    layers.MaxPool2D(pool_size=[2, 2],strides=2,padding='same'),                 #输入[b,4,4,512] -> b个图片512个输入pooling后[b,2,2,512]
    # unit 5
    layers.Conv2D(512, kernel_size=[3,3], padding='same', activation=tf.nn.relu),#输入[b,2,2,512] -> 卷积核[3,3,512,512] -> 输出[b,2,2,512]
    layers.Conv2D(512, kernel_size=[3,3], padding='same', activation=tf.nn.relu),#输入[b,2,2,512] -> 卷积核[3,3,512,512] -> 输出[b,2,2,512]
    layers.MaxPool2D(pool_size=[2, 2],strides=2,padding='same')                  #输入[b,2,2,512] -> b个图片512个输入pooling后[b,1,1,512]
]

def main():
    # 构建网络
    conv_net = Sequential(conv_layers)#[b,32,32,3] -> [b,1,1,512]
    fc_net = Sequential([             #[b,1,1,512] -> [b,100]
        layers.Dense(256, activation=tf.nn.relu),
        layers.Dense(128, activation=tf.nn.relu),
        layers.Dense(100, activation=None)])
    conv_net.build(input_shape=[None, 32, 32, 3])#卷积神经网络输入就是原图片
    fc_net.build(input_shape=[None,512])         #全连接层神经网络输入
    optimizer = optimizers.Adam(lr=1e-4)         #cifar比较复杂,步长小一点
    variables = conv_net.trainable_variables + fc_net.trainable_variables#这点是序列相加,类似拼接[1,2]+[3,4]->[1,2,3,4]

    for epoch in range(50):
        print('epoch:',epoch+1)
        for step ,(x,y) in enumerate(train_db):
            # 前向传播损失函数
            with tf.GradientTape() as tape :
                logits = fc_net(tf.reshape(conv_net(x),[-1,512]))
                loss = tf.reduce_mean(tf.losses.categorical_crossentropy(y, logits, from_logits=True))
            # 反向传播梯度更新
            grads = tape.gradient(loss,variables)
            optimizer.apply_gradients(zip(grads,variables))
            if step%10 == 0: print(f'step{step//10}','loss:%0.3f'%float(loss))
        # 前向传播验证正确率,可以用此方法的前提是lable是数字,也只有数字才可以用one_hot,因此只要可以one_hot都可以用此方法
        total_correct, total_num = 0, 0
        for x,y in test_db:
            logits = fc_net(tf.reshape(conv_net(x),[-1,512]))#卷积神经网络到最后图片的长宽维度都变成了一维,而且目前见过的全连接层目前都是二维矩阵相乘
            prob = tf.nn.softmax(logits, axis=1)
            total_correct += int(tf.reduce_sum(tf.cast(tf.equal(tf.cast(tf.argmax(prob, axis=1),dtype=tf.int32),y),dtype=tf.int32)))
            total_num += x.shape[0]
        accracy = total_correct / total_num
        print('accracy:','%0.3f%%'%(accracy*100),'\n')
# 运行程序,调用name方法
if __name__ == '__main__':
    main()

你可能感兴趣的:(TensorFlow下CIFAR10-100数据集的自动下载与处理(附百度网盘地址)及卷积神经网络处理Cifar100程序)