赞
踩
这是一个品牌分类任务,需要设计一个神经网络,识别出其正确率。采用DensNet121进行迁移学习。
- from sklearn import metrics
- import numpy as np
- import tensorflow as tf
- from tensorflow import keras
- from tensorflow.keras import Model, layers
- from tensorflow.keras import layers, optimizers, datasets, Sequential
- import os
- from tensorflow.python.keras import regularizers
-
- # 数据读取函数,返回训练集、验证集、测试集
-
- def get_data(height, width, batchsz):
- # 获取训练集
- filepath1 = '/content/drive/MyDrive/Colab Notebooks/Fashion_Dataset/train'
- train_ds = tf.keras.preprocessing.image_dataset_from_directory(
- filepath1, # 指定数据路径
- label_mode='categorical', # 导入的目标数据,进行onehot编码
- image_size=(height, width), # 对图像resize
- batch_size=batchsz, # 每次迭代的batchsize
- )
-
- # 获取验证集数据
- filepath2 = '/content/drive/MyDrive/Colab Notebooks/Fashion_Dataset/val'
- val_ds = tf.keras.preprocessing.image_dataset_from_directory(
- filepath2,
- label_mode='categorical',
- image_size=(height, width),
- batch_size=batchsz,
- )
-
- # 获取验证集数据
- filepath3 = '/content/drive/MyDrive/Colab Notebooks/Fashion_Dataset/test'
- test_ds = tf.keras.preprocessing.image_dataset_from_directory(
- filepath3,
- label_mode='categorical',
- image_size=(height, width),
- batch_size=batchsz,
- )
-
- return (train_ds, val_ds, test_ds)
-
- # 获取数据
- train_ds, val_ds, test_ds = get_data(224, 224, 64)
- # 查看分类名称
- class_names = train_ds.class_names
- print('分类名:', class_names)
- # 查看数据信息
- sample = next(iter(train_ds))
- print('x_batch.shape:', sample[0].shape, 'y_batch.shape:', sample[1].shape)
- # 构建归一化函数
- def processing(x, y):
- # 图像中的每个像素值映射到[-1,1]之间 归一化
- x = 2 * tf.cast(x, dtype=tf.float32) / 255.0 - 1
- y = tf.cast(y, dtype=tf.int32)
- # 返回处理后的结果
- return (x, y)
- #对数据进行洗牌
- train_ds = train_ds.map(processing).shuffle(10000)
- val_ds = val_ds.map(processing) # 验证集和测试集不需要打乱顺序
- test_ds = test_ds.map(processing)
- # 查看数据信息
- sample = next(iter(train_ds))
- print('x_batch.shape:', sample[0].shape, 'y_batch.shape:', sample[1].shape)
-
- #载入DensNet模型并进行网络微调
- def get_new_model():
- pre_model = tf.keras.applications.DenseNet121(
- # 不包括全连接层,导入预训练权重,自定义输入图片大小
- include_top=False, weights='imagenet', input_shape=[224, 224, 3]
- )
-
- # 冻住特征提取层
- for layer in pre_model.layers:
- # 正反向传播过程中权重参数不更新
- layer.trainable = False
-
- # 进行一次前向传播,看图像有何改变
- imgs, labels = next(iter(train_ds))
-
- # 获取训练集的某一个batch的图像及标签
- res = pre_model(imgs)
-
-
- # 微调网络
- # 解冻所有网络层
- pre_model.trainable = True
- print('numbers of layers:', len(pre_model.layers))
- # 查看一共有多少层:780
-
- # 指定冻结前500层
- find_tune_at = 500
-
- # 前500层在正方向传播过程中参数不能变,剩下的层权重参数可以调整
- for layer in pre_model.layers[:find_tune_at]: # 包括第500层
- layer.trainable = False
- # 构造输出层
- # 对特征提取层的输出进行全局平均池化
- x = layers.GlobalAveragePooling2D()(pre_model.output)
- x = layers.Flatten(name='flatten')(x)
- x = layers.Dense(2048, activation='relu', kernel_regularizer=regularizers.l2(0.0001))(x) #对数据进行正则化
- x = layers.BatchNormalization()(x)
- x = layers.Dense(1024, activation='relu', kernel_regularizer=regularizers.l2(0.0001))(x)
- x = layers.BatchNormalization(name='bn_fc_01')(x)
-
- #输出层分2类
- x = layers.Dense(2, activation='softmax')(x)
-
- # 构建模型
- model = Model(pre_model.input, x)
-
- #网络配置,调小学习率避免过拟合
- opt = optimizers.Adam(learning_rate=0.001)
-
- #编译
- model.compile(optimizer=opt, # 学习率
- loss='categorical_crossentropy', # 对onehot后的y,计算交叉熵损失
- metrics=['accuracy']) # 评价指标
-
- return model
-
- model = get_new_model()
- model.summary()
-
- from tensorflow.keras.callbacks import ModelCheckpoint
-
- checkpoint_path = '/content/drive/MyDrive/model_checkpoints' # 每次保存的都会覆盖旧的
- # 每次保存为一个新的文件
- checkpoint = ModelCheckpoint(filepath=checkpoint_path,
- save_freq='epoch', # 每个epoch结束就保存一次
- save_weights_only=True,
- verbose=1)
-
- # 训练,在上一次训练的基础上继续训练10次
- history_fine = model.fit(train_ds, # 训练集
- validation_data=val_ds, # 验证集
- epochs=25,
- callbacks=[checkpoint]) # 迭代次数修改epoch
-
- import matplotlib.pyplot as plt
- train_acc = history_fine.history['accuracy']
- test_acc = history_fine.history['val_accuracy']
- # 损失
- train_loss = history_fine.history['loss']
- test_loss = history_fine.history['val_loss']
- # 绘图
- # 准确率曲线
- plt.figure(figsize=(10, 5))
- plt.subplot(1, 2, 1)
- plt.plot(train_acc, label='train_acc')
- plt.plot(test_acc, label='test_acc')
- plt.title('accuracy')
- plt.legend() #显示图例label
- # 损失曲线
- plt.subplot(1, 2, 2)
- plt.plot(train_loss, label='train_loss')
- plt.plot(test_loss, label='test_loss')
- plt.title('loss')
- plt.legend()
- plt.show()
- test_loss, test_acc =model .evaluate(test_ds)
- print("Test loss: {:.3f}\nTest accuracy: {:.2f}%".format(test_loss, 100 * test_acc))
利用K折交叉熵
- from PIL import Image
-
- # 从文件夹读取图片和标签到numpy数组中
- # 标签信息在文件名中,burberry类型的衣服表示该图片的标签为0
- def read_data(data_dir):
- datas = []
- labels = []
-
- for fname in os.listdir(data_dir):
- if fname[:8] =='burberry':
- label = 0
- else:
- label = 1
-
- fpath = os.path.join(data_dir, fname)
- i=0
- for ffname in os.listdir(fpath):
- ffpath = os.path.join(fpath, ffname)
-
- image = Image.open(ffpath)
- image = image.resize((224,224),Image.LANCZOS)
-
-
-
- data = np.array(image) / 255.0
- label = label
- datas.append(data)
- labels.append(label)
-
-
-
- datas = np.array(datas)
- labels = np.array(labels)
-
- #print("shape of datas: {}\tshape of labels: {}".format(datas.shape,labels.shape))
- return datas, labels
-
-
- 将训练集和验证集合并为一个训练集
-
- def get_data(path="/content/drive/MyDrive/Colab Notebooks/Fashion_Dataset"):
- #将path修改为dataset路径
- train_x, train_y = read_data(os.path.join(path,'train'))
- val_x, val_y = read_data(os.path.join(path,'val'))
- test_x, test_y = read_data(os.path.join(path,'test'))
- #合并
- #train_x = np.vstack((train_x,val_x))
- #train_y = np.hstack((train_y,val_y))
- train_x = np.concatenate([train_x,val_x],axis=0)
- train_y = np.concatenate([train_y,val_y],axis=0)
- #训练集打乱
- train_x,train_y=shuffle_datas(train_x,train_y)
- print("shape of datas: {}\tshape of labels: {}".format(train_x.shape,train_y.shape))
- print("shape of datas: {}\tshape of labels: {}".format(test_x.shape,test_y.shape))
- return train_x,train_y,test_x,test_y
-
-
- # 对数据进行洗牌
- def shuffle_datas(x,y):
- index = [i for i in range(len(x))]
- np.random.shuffle(index)
- x = x[index]
- y = y[index]
- return x,y
-
- #获取数据
- train_x,train_y,test_x,test_y = get_data()
-
- K折交叉验证实现(k取5组)
-
- from tensorflow.keras.utils import to_categorical
-
- k=5
- num_epochs=25
-
- #算出滑动步长 x_data的shape为(70000,28,28) 划分5组 每个步长为14000
- slid_step=int(train_x.shape[0]/k)
-
- #数据类型转换
- train_x.astype(dtype='float32')
- train_y.astype(dtype="int32")
- #historys用来记录5组auc
- historys=[]
-
- #五组实验
- for i in range(k):
- x_test, y_test = train_x[i * slid_step:(i + 1) * slid_step],train_y[i * slid_step:(i + 1) * slid_step]
- x_train, y_train = train_x[i * slid_step:], train_y[i * slid_step:]
- #数据形状修改为相同
- y_train = to_categorical(y_train, 2)
- y_test = to_categorical(y_test, 2)
- #读取模型
- model = get_new_model()
- history =model.fit(x_train, y_train,epochs=num_epochs,
- validation_data=(x_test,y_test),
- batch_size=64)
- historys.append(history.history)
-
- 平均准确率
-
- acc_mean=[]
- for i in range(5):
- acc_mean=list(range(1,6)),list(historys[i].values())[1]
-
- print(acc_mean)
- print("平均值acc:",np.sum(list(historys[i].values())[1])/25)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。