第51章 使用ResNet实现CIFAR100数据集分类

了解了ResNet模型和CIFAR100数据集,完成了准备工作,现在可以着手开始使用ResNet实现CIFAR100数据集分类。

数据准备

直接使用上一章CIFAR100数据集获取的方法。


import tensorflow_datasets as tfds
import jax
import sys

sys.path.append("../50/")

import ResNet

def setup():
    
    (trains, tests), metas = tfds.load(name = "cifar100", data_dir = "/tmp/", split = [tfds.Split.TRAIN, tfds.Split.TEST], with_info = True, batch_size = -1)
    
    trains = tfds.as_numpy(trains)
    tests = tfds.as_numpy(tests)
    
    train_images, train_labels = trains["image"], trains["label"]
    test_images, test_labels = tests["image"], tests["label"]
    
    num_classes = 100
    
    train_images = jax.numpy.reshape(train_images, [-1, 3, 32, 32])
    test_images = jax.numpy.reshape(test_images, [-1, 3, 32, 32])
    
    train_images = jax.numpy.transpose(train_images, [0, 2, 3, 1])
    test_images = jax.numpy.transpose(test_images, [0, 2, 3, 1])
    
    train_labels = jax.nn.one_hot(train_labels, num_classes = num_classes)
    test_labels = jax.nn.one_hot(test_labels, num_classes = num_classes)
    
    init_random_params_function, predict_function = ResNet.ResNet50(100)
    
    prng = jax.random.PRNGKey(10)
    inputs_shape = [-1, 32, 32, 3]
    
    return (train_images, train_labels), (test_images, test_labels), (num_classes, prng, inputs_shape, init_random_params_function, predict_function)

def train():
    
    (train_images, train_labels), (test_images, test_labels), (num_classes, prng, inputs_shape, init_random_params_function, predict_function) = setup()
    
    print((train_images.shape, train_labels.shape), (test_images.shape, test_labels.shape), (num_classes, prng, inputs_shape, init_random_params_function, predict_function))
    
    # 100 ((50000, 32, 32, 3), (50000, 100)) ((10000, 32, 32, 3), (10000, 100))
    # 100 ((50000, 32, 32, 3), (50000,)) ((10000, 32, 32, 3), (10000,))
    
def main():
    
    train()
    
if __name__ == "__main__":
    
    main()

运行结果打印输出如下,


((50000, 32, 32, 3), (50000, 100)) ((10000, 32, 32, 3), (10000, 100)) (100, Array([ 0, 10], dtype=uint32), [-1, 32, 32, 3], <function serial.<locals>.init_fun at 0x7f54259700>, <function serial.<locals>.apply_fun at 0x7f54259790>)

模型设计

下面设计模型设计。


import sys

sys.path.append("../50/")

import ResNet

def verify_accuracy(params, batch):
    
    inputs, targets = batch
    
    predictions = predict(params, inputs)
    _classes = jax.numpy.argmax(predictions, axis = 1)
    targets = jax.numpy.argmax(targets, axis = 1)
    
    return jax.numpy.sum(_classes == targets)

组件设计

损失函数和参数更新函数设计。


# Loss Function
def loss_funciton(params, batch, predict_function):
    
    inputs, targets = batch
    
    losses = -targets * predict_function(params, inputs)
    losses = jax.numpy.sum(losses, axis = 1)
    losses = jax.numpy.mean(losses)
    
    return losses

# Params Update Function
def update_function(i, optimizer_state, optimizer_update_function, batch, predict_function):
    
    params = get_params_function(optimizer_state)
    
    loss_function_grad = jax.grad(loss_function)
    gradients = loss_function_grad(params, batch, predict_function)
    
    return optimizer_update_function(i, gradients, optimizer_state)

模型训练

全部代码如下,


import tensorflow_datasets as tfds
import jax
import jax.example_libraries.optimizers
import sys

sys.path.append("../50/")

import ResNet

def setup():
    
    (trains, tests), metas = tfds.load(name = "cifar100", data_dir = "/tmp/", split = [tfds.Split.TRAIN, tfds.Split.TEST], with_info = True, batch_size = -1)
    
    trains = tfds.as_numpy(trains)
    tests = tfds.as_numpy(tests)
    
    train_images, train_labels = trains["image"], trains["label"]
    test_images, test_labels = tests["image"], tests["label"]
    
    train_images = train_images.astype(jax.numpy.float32) / 225.0
    test_images = test_images.astype(jax.numpy.float32) / 225.0
    
    num_classes = 100
    
    #train_images = jax.numpy.reshape(train_images, [-1, 3, 32, 32])
    #test_images = jax.numpy.reshape(test_images, [-1, 3, 32, 32])
    
    # train_images = jax.numpy.transpose(train_images, [0, 2, 3, 1])
    # test_images = jax.numpy.transpose(test_images, [0, 2, 3, 1])
    
    train_labels = jax.nn.one_hot(train_labels, num_classes = num_classes)
    test_labels = jax.nn.one_hot(test_labels, num_classes = num_classes)
    
    init_random_params_function, predict_function = ResNet.ResNet50(100)
    
    prng = jax.random.PRNGKey(10)
    inputs_shape = [-1, 32, 32, 3]
    batch_size = 100
    total_number = 10000
    epochs = 2
    
    return (train_images, train_labels), (test_images, test_labels), (num_classes, prng, inputs_shape, batch_size, total_number, epochs, init_random_params_function, predict_function)

def verify_accuracy(params, batch):
    
    inputs, targets = batch
    
    predictions = predict(params, inputs)
    _classes = jax.numpy.argmax(predictions, axis = 1)
    targets = jax.numpy.argmax(targets, axis = 1)
    
    return jax.numpy.sum(_classes == targets)


# Loss Function
def loss_function(params, batch, predict_function):
    
    inputs, targets = batch
    
    losses = -targets * predict_function(params, inputs)
    losses = jax.numpy.sum(losses, axis = 1)
    losses = jax.numpy.mean(losses)
    
    return losses

# Params Update Function
def update_function(i, optimizer_state, get_params_function, optimizer_update_function, batch, predict_function):
    
    params = get_params_function(optimizer_state)
    
    loss_function_grad = jax.grad(loss_function)
    gradients = loss_function_grad(params, batch, predict_function)
    
    return optimizer_update_function(i, gradients, optimizer_state)

def train():
    
    (train_images, train_labels), (test_images, test_labels), (num_classes, prng, inputs_shape, batch_size, total_number, epochs, init_random_params_function, predict_function) = setup()
    
    print((train_images.shape, train_labels.shape), (test_images.shape, test_labels.shape), (num_classes, prng, inputs_shape, batch_size, total_number, epochs, init_random_params_function, predict_function))
    
    # 100 ((50000, 32, 32, 3), (50000, 100)) ((10000, 32, 32, 3), (10000, 100))
    # 100 ((50000, 32, 32, 3), (50000,)) ((10000, 32, 32, 3), (10000,))
    
    optimizer_init, optimizer_update, get_params = jax.example_libraries.optimizers.adam(step_size = 1e-4)
    _, init_params = init_random_params_function(prng, inputs_shape)
    optimizer_state = optimizer_init(init_params)
    
    batch_number = total_number // batch_size
    
    for i in range(epochs):
        
        for j in range(batch_number):
        
            start = j * batch_size
            end = (j + 1) * batch_size
            
            batch = (train_images[start: end], train_labels[start: end])
            # def update_function(i, optimizer_state, get_params_function, optimizer_update_function, batch, predict_function):
            optimizer_state = update_function(i, optimizer_state, get_params, optimizer_update, batch, predict_function)
            
            if (j + 1) % 10 == 0:
                
                params = get_params(optimizer_state)
                # def loss_function(params, batch, predict_function):
                losses = loss_function(params, batch, predict_function)
                
                print("Losses = ", losses)
                
    params = get_params(optimizer_state)
    
    accuracies = []
    predictions = 0.0
    
    for i in range(epochs):
        
        start = i * batch_size
        end = (i + 1) * batch_size
        
        batch = (test_images[start: end], test_labels[start: end])
        
        predictions += verify_accuracy(params, batch)
        
    accuracies.append(predictions / float(total_number))
    
    print("Accuracies = ", {accuracies})
        
def main():
    
    train()
    
if __name__ == "__main__":
    
    main()

根据自己设备的硬件配置,适时调整参数和训练集的batch_size可以做出调整。

结论

本章总结上两章学到的知识,利用CIFAR100和ResNet50模型,完成了CIFAR100分类任务。

最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容