GoogLeNet 训练

模型文件

from tensorflow.keras import layers, models, Model, Sequential


def GoogLeNet(im_height=224, im_width=224, class_num=1000, aux_logits=False):
    # 输入224*224的3通道彩色图片
    input_image = layers.Input(shape=(im_height, im_width, 3), dtype="float32")
    x = layers.Conv2D(64, kernel_size=7, strides=2, padding="SAME", activation="relu", name="conv2d_1")(input_image)
    x = layers.MaxPool2D(pool_size=3, strides=2, padding="SAME", name="maxpool_1")(x)
    x = layers.Conv2D(64, kernel_size=1, activation="relu", name="conv2d_2")(x)
    x = layers.Conv2D(192, kernel_size=3, padding="SAME", activation="relu", name="conv2d_3")(x)
    x = layers.MaxPool2D(pool_size=3, strides=2, padding="SAME", name="maxpool_2")(x)
    # Inception模块
    x = Inception(64, 96, 128, 16, 32, 32, name="inception_3a")(x)
    x = Inception(128, 128, 192, 32, 96, 64, name="inception_3b")(x)
    x = layers.MaxPool2D(pool_size=3, strides=2, padding="SAME", name="maxpool_3")(x)
    # Inception模块
    x = Inception(192, 96, 208, 16, 48, 64, name="inception_4a")(x)
    # 判断是否使用辅助分类器1。训练时使用,测试时去掉。
    if aux_logits:
        aux1 = InceptionAux(class_num, name="aux_1")(x)
    # Inception模块
    x = Inception(160, 112, 224, 24, 64, 64, name="inception_4b")(x)
    x = Inception(128, 128, 256, 24, 64, 64, name="inception_4c")(x)
    x = Inception(112, 144, 288, 32, 64, 64, name="inception_4d")(x)
    # 判断是否使用辅助分类器2。训练时使用,测试时去掉。
    if aux_logits:
        aux2 = InceptionAux(class_num, name="aux_2")(x)
    # Inception模块
    x = Inception(256, 160, 320, 32, 128, 128, name="inception_4e")(x)
    x = layers.MaxPool2D(pool_size=3, strides=2, padding="SAME", name="maxpool_4")(x)
    # Inception模块
    x = Inception(256, 160, 320, 32, 128, 128, name="inception_5a")(x)
    x = Inception(384, 192, 384, 48, 128, 128, name="inception_5b")(x)
    # 平均池化层
    x = layers.AvgPool2D(pool_size=7, strides=1, name="avgpool_1")(x)
    # 拉直
    x = layers.Flatten(name="output_flatten")(x)
    x = layers.Dropout(rate=0.4, name="output_dropout")(x)
    x = layers.Dense(class_num, name="output_dense")(x)
    aux3 = layers.Softmax(name="aux_3")(x)
    # 判断是否使用辅助分类器
    if aux_logits:
        model = models.Model(inputs=input_image, outputs=[aux1, aux2, aux3])
    else:
        model = models.Model(inputs=input_image, outputs=aux3)
    return model


class Inception(layers.Layer):
    # ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj分别对应Inception中各个卷积核的个数,**kwargs可变长度字典变量,存放层名称
    def __init__(self, ch1x1, ch3x3red, ch3x3, ch5x5red, ch5x5, pool_proj, **kwargs):  
        super(Inception, self).__init__(**kwargs)
        # 分支1
        self.branch1 = layers.Conv2D(ch1x1, kernel_size=1, activation="relu")
        # 分支2
        self.branch2 = Sequential([  
            layers.Conv2D(ch3x3red, kernel_size=1, activation="relu"),
            layers.Conv2D(ch3x3, kernel_size=3, padding="SAME", activation="relu")])
        # 分支3
        self.branch3 = Sequential([
            layers.Conv2D(ch5x5red, kernel_size=1, activation="relu"),
            layers.Conv2D(ch5x5, kernel_size=5, padding="SAME", activation="relu")])      
        # 分支4
        self.branch4 = Sequential([
            layers.MaxPool2D(pool_size=3, strides=1, padding="SAME"),  
            layers.Conv2D(pool_proj, kernel_size=1, activation="relu")])

    def call(self, inputs, **kwargs):
        branch1 = self.branch1(inputs)
        branch2 = self.branch2(inputs)
        branch3 = self.branch3(inputs)
        branch4 = self.branch4(inputs)
        outputs = layers.concatenate([branch1, branch2, branch3, branch4])  # 将4个分支输出按通道连接
        return outputs


class InceptionAux(layers.Layer):
    # num_classes表示输出分类节点数,**kwargs存放每层名称
    def __init__(self, num_classes, **kwargs):
        super(InceptionAux, self).__init__(**kwargs)
        self.averagePool = layers.AvgPool2D(pool_size=5, strides=3)  # 平均池化
        self.conv = layers.Conv2D(128, kernel_size=1, activation="relu")

        self.fc1 = layers.Dense(1024, activation="relu")  # 全连接层1
        self.fc2 = layers.Dense(num_classes)  # 全连接层2
        self.softmax = layers.Softmax()  # softmax激活函数

    def call(self, inputs, **kwargs):
        x = self.averagePool(inputs)
        x = self.conv(x)
        x = layers.Flatten()(x)  # 拉直
        x = layers.Dropout(rate=0.5)(x)
        x = self.fc1(x)
        x = layers.Dropout(rate=0.5)(x)
        x = self.fc2(x)
        x = self.softmax(x)
        return x

main程序

import tensorflow as tf
import numpy as np
import os
from model import GoogLeNet
from random import shuffle
import cv2 as cv
from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics, losses

name_dict = {"BF":0,"BK":1,"BL":2,"BR":3,"CF":4,"CL":5,"CV":6,"CXK":7,"S":8,"XF":9}

data_root_path = "color_part_data_processing/"
test_file_path =  "TXT_doc/test.txt"  #测试集数据集文件
trainer_file_path = "TXT_doc/trainer.txt"  #训练集数据集文件

name_data_list = {}  #记录每类图片有多少训练图片、测试图片

trainer_list = []
test_list = []

#将图片完整路径存入字典
def save_train_test_file(path,name):
    if name not in name_data_list:
        img_list =[]
        img_list.append(path)
        name_data_list[name] = img_list
    else:
        name_data_list[name].append(path)

#遍历数据集目录,提取出图片路径,分训练集、测试集
dirs = os.listdir(data_root_path)
for d in dirs:
    full_path = data_root_path + d
    if os.path.isdir(full_path):
        imgs = os.listdir(full_path)  #列出子目录中所有图片
        for img in imgs:
            save_train_test_file(full_path+ "/" + img, d)

#将字典中的内容写入测试集、训练集文件
with open(test_file_path, "w") as f: #清空测试集文件
    pass
with open(trainer_file_path, "w") as f:  #清空训练集文件
    pass

#遍历字典,分数据
for name,img_list in name_data_list.items():
    i = 0
    num = len(img_list)
    print(f"{name}:{num}张")
    for img in img_list:
        if i % 10 == 0:
            test_list.append(f"{img}\t{name_dict[name]}\n")
        else:
            trainer_list.append(f"{img}\t{name_dict[name]}\n")
        i += 1
with open(trainer_file_path,"w") as f:
    shuffle(trainer_list)
    f.writelines(trainer_list)

with open(test_file_path,"w") as f:
    f.writelines(test_list)

print("---------------------------------------------------之前的代码主要是生成.txt文件便于找到图片和对应的标签-------------------------------------------------")

def generateds(train_list):
    x, y_ = [], []  # x图片数据,y_为标签
    with open(train_list,'r') as f:
        #读取所有行
        lines = [line.strip()for line in f] #对数据进行掐头去尾放入列表
        for line in lines:
            img_path, lab = line.strip().split("\t")
            img = cv.imread(img_path) #读入图片
            img = cv.resize(img,(224,224)) ####对图片进行放缩**********************************
            # img = np.array(img.convert('L')) #将图片变为8位宽灰度值的np.array格式
            img = img / 255 #数据归一化(实现预处理)
            x.append(img) #归一化后的数据,贴到列表x
            y_.append(lab)

    x = np.array(x)
    y_ = np.array(y_)
    y_ = y_.astype(np.int64)
    return x, y_

x_train , y_train = generateds(trainer_file_path)
x_test, y_test = generateds(test_file_path)
x_train = tf.convert_to_tensor(x_train,dtype=tf.float32)
y_train = tf.convert_to_tensor(y_train,dtype=tf.int32)
x_test = tf.convert_to_tensor(x_test,dtype=tf.float32)
y_test = tf.convert_to_tensor(y_test,dtype=tf.int32)
train_dataset = tf.data.Dataset.from_tensor_slices((x_train,y_train)) #构建数据集对象
train_dataset = train_dataset.batch(32)  #设置批量训练的batch为32,要将训练集重复训练10遍
test_dataset = tf.data.Dataset.from_tensor_slices((x_test,y_test))
test_dataset = test_dataset.batch(32)
print("---------------------------------------------网络数据集搭建完成------------------------------------")
# model = tf.keras.models.Sequential([
#     tf.keras.layers.Flatten(),
#     tf.keras.layers.Dense(128,activation='relu'),
#     tf.keras.layers.Dense(10,activation='softmax')
# ])
print('---------------------------------------------模型搭建--------------------------------------------')

model = GoogLeNet(im_height=224,im_width=224,class_num=10,aux_logits=True) #实例化模型
model.build((32,224,224,3))


print('---------------------------------------------建立优化器-------------------------------------------')
loss_object = tf.keras.losses.CategoricalCrossentropy(from_logits=False)  # 定义损失函数(这种方式需要one-hot编码)
optimizer = optimizers.SGD(lr=0.01)  # 声明采用批量随机梯度下降方法,学习率=0.01
acc_meter = metrics.Accuracy()  # 新建accuracy测量器

train_loss = tf.keras.metrics.Mean(name='train_loss')
train_accuracy = tf.keras.metrics.CategoricalAccuracy(name='train_accuracy')  # 定义平均准确率

test_loss = tf.keras.metrics.Mean(name='test_loss')
test_accuracy = tf.keras.metrics.CategoricalAccuracy(name='test_accuracy')


@tf.function
def train_step(images, labels):
    with tf.GradientTape() as tape:
        aux1, aux2, output = model(images, training=True)
        labels = tf.one_hot(labels,depth=10) #one-hot编码
        loss1 = loss_object(labels, aux1)   # 辅助分类器损失函数
        loss2 = loss_object(labels, aux2)
        loss3 = loss_object(labels, output)  # 主分类器损失函数
        loss = loss1*0.3 + loss2*0.3 + loss3  # 总损失函数
    gradients = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))
    train_loss(loss)
    train_accuracy(labels, output)

@tf.function
def test_step(images, labels):
    _, _, output = model(images, training=False)
    labels = tf.one_hot(labels, depth=10)  # one-hot编码
    t_loss = loss_object(labels, output)
    test_loss(t_loss)
    test_accuracy(labels, output)
print('------------------------------------------------------------------------------------------------')

best_test_loss = float('inf')
best_test_accuracy = float('inf')
epochs= 1000
for epoch in range(1, epochs+1):
    train_loss.reset_states()        # 训练损失值清零
    train_accuracy.reset_states()    # clear history info
    test_loss.reset_states()         # clear history info
    test_accuracy.reset_states()     # clear history info

    for step,(images,labels) in enumerate(train_dataset):
        train_step(images,labels)

    for step,(imags_val,labels_val) in enumerate(test_dataset):
        test_step(imags_val,labels_val)


    template = 'Epoch {}, Loss: {}, Accuracy: {}, Test Loss: {}, Test Accuracy: {}'
    print(template.format(epoch,
                          train_loss.result(),
                          train_accuracy.result() * 100,
                          test_loss.result(),
                          test_accuracy.result() * 100))
    if test_loss.result() < best_test_loss:
        best_test_loss = test_loss.result()
        print('best_test_loss:',best_test_loss)
    if test_accuracy.result() > best_test_accuracy:
        best_test_accuracy = test_accuracy.result()
        print('best_test_accracy:',best_test_accuracy)
print('******************************best_test_accuracy*****************************',best_test_accuracy)
        # model.save_weights("./save_weights/myGoogLeNet.h5")   # 保存模型为.h5格式

训练结果测试集准确率在80左右。最好的一次准确率为84.78261%

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值