Tensorflow 卷积神经网络 (四)cifar100实战

61 篇文章 6 订阅
39 篇文章 2 订阅

这里根据keras提供的cifar100的数据集做一个实战案例的回顾

CIFAR100是一个有100个类别的图片数据集,其体量比CIFAR10大了不是一点点,那么我们要如何更好的处理这样大批量的数据集呢,这里使用卷积神经网络进行解决

其网络结构如下图:

上代码

import tensorflow as tf

from tensorflow.keras import layers, optimizers, datasets, Sequential
import os

os.environ['TP_CPP_MIN_LOG_LEVEL'] = '2'
tf.random.set_seed(2345)
#这里使用的是Sequential结构来构建网络,我们先通过调用keras里边的layers进行
#构建一个layers的网络架构,这里构建的是一个5层的卷积神经网络
conv_layers = [
    # unit 1
    layers.Conv2D(64, kernel_size = [3,3], padding = 'same', activation = tf.nn.relu),
    layers.Conv2D(64, kernel_size = [3,3], padding = 'same', activation = tf.nn.relu),
    layers.MaxPool2D(pool_size = [2,2], strides = 2, padding = 'same'),
    #卷积网络一般是由两个卷积层和一个池化采样层组合构成的,这里kernel size同一位3*3,池化采样的pool size则为2*2
    # unit 2 这里第一个参数128是指这个卷积层输出数据的纬度,即卷积核的个数-》batch,其与输出的通道数是一样的
    #可以看到我们的通道数从3变化为了64 -》 128 -》 256 -》 512
    layers.Conv2D(128, kernel_size = [3,3], padding = 'same',activation= tf.nn.relu),
    layers.Conv2D(128, kernel_size = [3,3], padding = 'same', activation = tf.nn.relu),
    layers.MaxPool2D(pool_size=[2,2], strides = 2, padding = 'same'),

    # unit 3
    layers.Conv2D(256, kernel_size = [3,3], padding = 'same',activation= tf.nn.relu),
    layers.Conv2D(256, kernel_size = [3,3], padding = 'same', activation = tf.nn.relu),
    layers.MaxPool2D(pool_size=[2,2], strides = 2, padding = 'same'),

    # unit 4
    layers.Conv2D(512, kernel_size = [3,3], padding = 'same',activation= tf.nn.relu),
    layers.Conv2D(512, kernel_size = [3,3], padding = 'same', activation = tf.nn.relu),
    layers.MaxPool2D(pool_size=[2,2], strides = 2, padding = 'same'),

    # unit 5
layers.Conv2D(512, kernel_size = [3,3], padding = 'same',activation= tf.nn.relu),
    layers.Conv2D(512, kernel_size = [3,3], padding = 'same', activation = tf.nn.relu),
    layers.MaxPool2D(pool_size=[2,2], strides = 2, padding = 'same'),

]


def preprocess(x, y):
    x = tf.cast(x, dtype = tf.float32) / 255.
    y = tf.cast(y, dtype = tf.int32)
    return x, y
    #尝龟的归一化操作



(x, y), (x_test, y_test) = datasets.cifar100.load_data()
#读入数据
y = tf.squeeze(y, axis = 1)
#把label去掉第二个维度,只留下一个维度作为标签
y_test = tf.squeeze(y_test, axis = 1)
print(x.shape, y.shape, x_test.shape, y_test.shape)

train_db = tf.data.Dataset.from_tensor_slices((x, y))
#将数据转换为tensor形式的张量
train_db = train_db.shuffle(1000).map(preprocess).batch(128)
#打乱数据集,并进行预处理,划分为128个为一组的batch

test_db = tf.data.Dataset.from_tensor_slices((x_test, y_test))
test_db = test_db.amp(preprocess).batch(64)
#作为测试集我们就不需要打乱了

sample = next(iter(train_db))
#合理通过next(iter())创建一个可以迭代的对象sample
print('sample:', sample[0].shape, sample[1].shape,
      tf.reduce_min(sample[0]), tf.reduce_max(sample[0]))

def main():
    conv_net = Sequential(conv_layers)
    #通过之前的list构建卷积网络,下面这个是同理构建全连接层的
    fc_net = Sequential([
        layers.Dense(256,activation = tf.nn.relu),
        layers.Dense(128, activation = tf.nn.relu),
        layers.Dense(100, activation = None),
    ])
    #这里我们使用build方法构建对应网络结构,输入第一个为none时表示我们输入的图像个数适应于数据集
    #而其原始维度是32*32 通道数为3
    conv_net.build(input_shape = [None, 32, 32, 3])
    fc_net.build(input_shape= [None, 512])
    #这里因为最后一个卷积层输出的通道数为512所以全连接层通道数参数为512
    #[b, 32, 32, 3] => [b, 1, 1, 512]
    optimizer = optimizers.Adam(lr = 1e-4)
    #使用Adam 优化器 学习率设置为1e-4

    # 梯度下降的求梯度我们需要把卷积核全连接的参数汇总到一块
    variables = conv_net.trainable_variables + fc_net.trainable_variables

    for epoch in range(50):

        for step, (x, y) in enumerate(train_db):

            with tf.GradientTape() as tape:
                """[b, 32, 32, 3] => [b, 1, 1, 512]"""
                #将原始输入的 32 * 32 转变为全连接层的 1*1 512
                out = conv_net(x)
                # flatten打平512的操作
                out = tf.reshape(out, [-1, 512])
                # 这里是100分类问题所以我们还需要将512通道的数据转换为b,100维的数据进行loss计算
                logits = fc_net(out)
                # [b] => [b, 100] 这里引入onehot将原始标签进行独热编码
                y_onehot = tf.one_hot(y, depth = 100)
                #计算损失函数值
                loss = tf.losses.categorical_crossentropy(y_onehot, logits, from_logits = True)
                loss = tf.reduce_mean(loss)

            grads = tape.gradient(loss, variables)
            optimizer.apply_gradients(zip(grads, variables))

            if step % 100 == 0:
                print(epoch, step, 'loss', float(loss))


        total_num = 0
        total_correct = 0
        for x,y in test_db:

            out = conv_net(x)
            out = tf.reshape(out, [-1,512])
            #-1表示不用指定通过后面的512来限定计算这个维度
            logits = fc_net(out)
            prob = tf.nn.softmax(logits, axis = 1)
            #将输出进行softmax激活函数映射为0-1之间的值
            pred = tf.argmax(prob, axis = 1)
            pred = tf.cast(pred, dtype = tf.int32)
            
            correct = tf.cast(tf.equal(pred, y), dtype = tf.int32)
            correct = tf.reduce_sum(correct)
            
            total_num += x.shape[0]
            total_correct += int(correct)
            
            
        acc = total_correct / total_num
        print(epoch, 'acc:', acc)
        
if __name__ == '__main__':
    main()
            




 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值