使用keras实现。比较简单。这里就是做个思路的总结和代码的注释。
首先我们要准备好环境和数据集。
emmmmmmmm,https://keras.io/examples/cifar10_cnn/
上面的链接是keras官网的教学代码,十分简洁。我也是这个。
首先学习一下cifar10的数据集:https://www.cs.toronto.edu/~kriz/cifar.html
数据集中有如下几个文件:
batches.meta
data_batch_1
data_batch_2
data_batch_3
data_batch_4
data_batch_5
test_batch
这些文件都是 生成的。所以我们用人家官网的函数进行拆包,拆开后是一个字典。
可以用for in看看都有那些数据项。
拆包函数:
def unpickle(file):
import pickle
with open(file, 'rb') as fo:
dict = pickle.load(fo, encoding='bytes')
return dict
用for in 看看发现,其中batches.meta里边包含了:
b'num_cases_per_batch' #数据的多少
b'label_names' #标签的名字
b'num_vis' #***
这三个数据项,注意这些关键字都是bytes类型的,并不是字符串。
我们做分类其实就只是需要数据和标签就好,标签也是一个整型数而已。
比如我们这次要做一个10个物品的一个分类,那么我们的标签的数值范围就是0-9喽,
作为入门的卷积神经网络,我们只需要把最后的输出层调成10个神经元就好。
所以,这里的label_name可以作为一个映射,最后我们预测时方便自己阅读而已。
data_batch_1-5是训练集,每个文件有10000张图片,大小是1000032323
总共5个文件合并到一起就是5000032323
test_batch是预测集,有10000张图片,大小是100003232*3
下面为代码:(其中我没有使用keras自带的那个加载数据的函数,为了更好的理解,所以自己写了加载数据的函数)
首先是加载数据标签的代码:class_name.py
file = "data/batches.meta" def unpickle(file): import pickle with open(file, 'rb') as fo: dict = pickle.load(fo, encoding='bytes') return dict def readClassName(): result = unpickle(file) label_name = result[b'label_names'] return label_name if __name__=="__main__": result = unpickle(file) label_name = result[b'label_names'] print(label_name)
emmmm,没啥可解释的。
下面是加载数据的代码:load_data.py
import numpy as np import cv2 def unpickle(file): import pickle with open(file, 'rb') as fo: dict = pickle.load(fo, encoding='bytes') return dict #将一张3072的一维图片调整成32*32*3的三维图片格式 def arraytoimage(image): r = image[0:1024] g = image[1024:2048] b = image[2048:] r = np.reshape(r, (32, 32)) g = np.reshape(g, (32, 32)) b = np.reshape(b, (32, 32)) image = cv2.merge([r,g,b]) return image #读取训练集的一个文件 def load_one_train_batch(no): file_path = "data/data_batch_" file_path+=str(no) file = unpickle(file_path) data = file[b'data'] label = file[b'labels'] result = [] for i in data: #由于一直图片是以rgb的形式存放的,是一个以为的向量3072 #我们需要将其调整成32*32*3这样的三维向量,因为我们需要把这个作为卷积层的输入,这样才能使用 #特征提取器,即卷积核来提取特征,从而识别物品 image = arraytoimage(i) result.append(image) return result,label #读取测试集 def load_test_batch(): file_path = "data/test_batch" file = unpickle(file_path) data = file[b'data'] label = file[b'labels'] result = [] for image in data: image = arraytoimage(image) result.append(image) return result, label #读取数据,里边包含对训练集的读取和对测试集的读取 def load_data(): #load tarin data train_datas = [] train_labels = [] for i in range(1,6): data,label = load_one_train_batch(i) train_datas.append(data) train_labels.append(label) #由于放回回来的数据类型为list不能用,所以调整为np.array类型的 train_datas = np.reshape(train_datas,(50000,32,32,3)) train_labels = np.reshape(train_labels,(50000,1)) #load test data test_data,test_label = load_test_batch() test_data = np.reshape(test_data,(10000,32,32,3)) test_label = np.reshape(test_label,(10000,1)) return (train_datas,train_labels),(test_data,test_label) if __name__=="__main__": (train_datas,train_labels),(test_data,test_label) = load_data()
emmm,这样数据读取就搞定了,就剩下使用keras定义卷积神经网络,并进行训练就好了。
代码:cifar10.py
import tensorflow as tf from keras.datasets import cifar10 from keras.utils import np_utils from keras.models import Sequential from keras.layers import Dense,Dropout,Activation,Flatten,Conv2D,MaxPooling2D,ZeroPadding2D from keras.utils.training_utils import multi_gpu_model #导入keras多GPU函数 import matplotlib.pyplot as plt import numpy as np import pandas as pd from class_name import readClassName import load_data np.random.seed(10) model_path = "model/cifarCnnModel_1.h5" #读取类别的名字到label_names label_names = readClassName() #根据图片实际的结果和预测的结果,画出来从idx开始的10个图像 def plot_images_lables_prediction(images,lables,prediction,idx,num=10): flg = plt.gcf() flg.set_size_inches(12,14) if num>25:num=25 for i in range(0,num): ax=plt.subplot(5,5,i+1) ax.imshow(images[idx],cmap='binary') title = str(i)+','+str(label_names[lables[i][0]],encoding="utf8") if len(prediction)>0: title+="=>"+str(label_names[prediction[i]],encoding="utf8") ax.set_title(title,fontsize=10) ax.set_xticks([]) ax.set_yticks([]) idx+=1 plt.show() #显示训练的记录 def show_train_history(train_history,train,validation): plt.plot(train_history.history[train]) plt.plot(train_history.history[validation]) plt.title("Train history") plt.ylabel(train) plt.xlabel('Epoch') plt.legend(['train','validation'],loc='upper left') plt.show() if __name__=="__main__": #官方函数的读取数据方法 #(x_img_train,y_lable_train),(x_img_test,y_lable_test)=cifar10.load_data() #根据我们的加载数据的方法 (x_img_train, y_lable_train), (x_img_test, y_lable_test) = load_data.load_data() print(type(x_img_train)) print(np.shape(x_img_train)) print(type(y_lable_train)) print(np.shape(y_lable_train)) ''' <class 'numpy.ndarray'> (50000, 32, 32, 3) <class 'numpy.ndarray'> (50000, 1) ''' print('train:',len(x_img_train)) print('test:',len(x_img_test)) y_lable_train_OneHot = np_utils.to_categorical(y_lable_train) y_lable_test_OneHot = np_utils.to_categorical(y_lable_test) ''' 将训练和测试用的标签从一个0-9的整数,转化为一个长度为10的向量,那么50000个训练的标签 最终就是50000*10的一个ndarry <class 'numpy.ndarray'> (50000, 10) ''' #二值化 x_img_train_normalize = x_img_train.astype('float32') / 255 x_img_test_normalize = x_img_test.astype('float32') / 255 #建立模型 model = Sequential() #建立卷积层1,池化层1 model.add(Conv2D(filters=32, kernel_size=(3,3), input_shape=(32,32,3), activation='relu', padding='same')) #假如Dropout,防止过拟合 model.add(Dropout(0.25)) #建立卷积层2 model.add(Conv2D(filters=32, kernel_size=(3,3), activation='relu', padding='same')) #建立池化层1 model.add(MaxPooling2D(pool_size=(2,2))) #建立平坦层 model.add(Flatten()) # 假如Dropout,防止过拟合 model.add(Dropout(0.25)) #建立隐藏层1 model.add(Dense(2500,activation='relu')) #建立输出层 model.add(Dense(10,activation='softmax')) #print(model.summary()) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) try: model.load_weights(model_path) print("加载模型成功!") except: print("加载模型失败!") #输出对模型的总结 #model.summary() train_history = model.fit(x=x_img_train_normalize, #训练数据 y=y_lable_train_OneHot, #训练数据的OneHot标签 validation_split=0.2, #validation_split用于在没有提供验证集的时候,按一定比例从训练集中取出一部分作为验证集 epochs=1, #训练的轮数 batch_size=300, #https://blog.csdn.net/Mr_Brooks/article/details/80277114 verbose=2) #https://blog.csdn.net/my_kingdom/article/details/84313683 #保存权重模型 model.save_weights(model_path) print("model save success!") #显示训练的记录 show_train_history(train_history,'acc','val_acc') show_train_history(train_history, 'loss', 'val_loss') #使用测试集对训练的模型进行评估 scores = model.evaluate(x_img_test_normalize, y_lable_test_OneHot, verbose=0) print('accuracy=', scores[1]) #对测试集进行预测 prediction = model.predict_classes(x_img_test_normalize) #展示出0-10这10个预测结果 plot_images_lables_prediction(x_img_test,y_lable_test,prediction,0,10)
以上就是cifar10 的全部内容
下面cifar100也是一样的写法
cifar100所提供的数据的标签有一个细标签,一个粗标签,然而我并不像关注那个粗标签,直接把细标签作为了图像的label。
class_name.py:
def unpickle(file): import pickle with open(file, 'rb') as fo: dict = pickle.load(fo, encoding='bytes') return dict def readClassName(): file_path = "data/cifar-100-python/meta" dic = unpickle(file_path) ''' b'fine_label_names' b'coarse_label_names' ''' fine_label_names = dic[b'fine_label_names'] coarse_label_names = dic[b'coarse_label_names'] return fine_label_names,coarse_label_names if __name__=="__main__": f,c = readClassName() print(f) print(c)
load_data.py
import numpy as np import cv2 import class_name image_no = 10 def arraytoimage(image): r = image[0:1024] g = image[1024:2048] b = image[2048:] r = np.reshape(r, (32, 32)) g = np.reshape(g, (32, 32)) b = np.reshape(b, (32, 32)) image = cv2.merge([r,g,b]) return image def unpickle(file): import pickle with open(file, 'rb') as fo: dict = pickle.load(fo, encoding='bytes') return dict def load_train_data(): file_path = "data/cifar-100-python/train" train_data = unpickle(file_path) ''' b'filenames' b'batch_label' b'fine_labels' b'coarse_labels' b'data' ''' # 因为fine这个细标签就是了,他的范围为0-99的,我直接做一个中文对应就好 f, c = class_name.readClassName() data = train_data[b'data'] fine_labels = train_data[b'fine_labels'] datas = [] labels = [] for i in range(len(data)): datas.append(arraytoimage(data[i])) labels.append(fine_labels[i]) datas = np.reshape(datas, (50000, 32, 32, 3)) labels = np.reshape(labels, (50000, 1)) return datas, labels def load_test_data(): file_path = "data/cifar-100-python/test" train_data = unpickle(file_path) # 因为fine这个细标签就是了,他的范围为0-99的,我直接做一个中文对应就好 f, c = class_name.readClassName() data = train_data[b'data'] fine_labels = train_data[b'fine_labels'] datas = [] labels = [] for i in range(len(data)): datas.append(arraytoimage(data[i])) labels.append(fine_labels[i]) # print(np.shape(datas)) # print(np.shape(labels)) datas = np.reshape(datas, (10000, 32, 32, 3)) labels = np.reshape(labels, (10000, 1)) return datas, labels def load_data(): train_data,train_label=load_train_data() test_data,test_label=load_test_data() return (train_data,train_label),(test_data,test_label) if __name__=="__main__": (x_img_train, y_lable_train), (x_img_test, y_lable_test) = load_data()
cifar100.py:
import tensorflow as tf from keras.datasets import cifar10 from keras.utils import np_utils from keras.models import Sequential from keras.layers import Dense,Dropout,Activation,Flatten,Conv2D,MaxPooling2D,ZeroPadding2D from keras.utils.training_utils import multi_gpu_model #导入keras多GPU函数 import os import matplotlib.pyplot as plt import numpy as np import pandas as pd from class_name import readClassName import load_data np.random.seed(10) model_path = "model/cifar100CnnModel_1.h5" fine_label_names,coarse_label_names = readClassName() def plot_images_lables_prediction(images,lables,prediction,idx,num=10): flg = plt.gcf() flg.set_size_inches(12,14) if num>25:num=25 for i in range(0,num): ax=plt.subplot(5,5,i+1) ax.imshow(images[idx],cmap='binary') label_name = str(fine_label_names[lables[i][0]], encoding="utf8") title = str(i)+','+label_name if len(prediction)>0: title+="=>"+label_name ax.set_title(title,fontsize=10) ax.set_xticks([]) ax.set_yticks([]) idx+=1 plt.show() def show_train_history(train_history,train,validation): plt.plot(train_history.history[train]) plt.plot(train_history.history[validation]) plt.title("Train history") plt.ylabel(train) plt.xlabel('Epoch') plt.legend(['train','validation'],loc='upper left') plt.show() if __name__=="__main__": (x_img_train, y_lable_train), (x_img_test, y_lable_test) = load_data.load_data() print(type(x_img_train)) print(np.shape(x_img_train)) print(type(y_lable_train)) print(np.shape(y_lable_train)) ''' <class 'numpy.ndarray'> (50000, 32, 32, 3) <class 'numpy.ndarray'> (50000, 1) ''' print('train:',len(x_img_train)) print('test:',len(x_img_test)) y_lable_train_OneHot = np_utils.to_categorical(y_lable_train) y_lable_test_OneHot = np_utils.to_categorical(y_lable_test) #二值化 x_img_train_normalize = x_img_train.astype('float32') / 255 x_img_test_normalize = x_img_test.astype('float32') / 255 #建立模型 model = Sequential() #建立卷积层1,池化层1 model.add(Conv2D(filters=32, kernel_size=(3,3), input_shape=(32,32,3), activation='relu', padding='same')) #假如Dropout,防止过拟合 model.add(Dropout(0.25)) #建立卷积层2 model.add(Conv2D(filters=32, kernel_size=(3,3), activation='relu', padding='same')) #建立池化层1 model.add(MaxPooling2D(pool_size=(2,2))) #建立平坦层 model.add(Flatten()) # 假如Dropout,防止过拟合 model.add(Dropout(0.25)) #建立隐藏层1 model.add(Dense(2500,activation='relu')) #建立输出层 model.add(Dense(100,activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) try: model.load_weights(model_path) print("加载模型成功!") except: print("加载模型失败!") model.summary() train_history = model.fit(x=x_img_train_normalize, y=y_lable_train_OneHot, validation_split=0.2, epochs=2, batch_size=300, verbose=2) model.save_weights(model_path) print("model save success!") show_train_history(train_history,'acc','val_acc') show_train_history(train_history, 'loss', 'val_loss') scores = model.evaluate(x_img_test_normalize, y_lable_test_OneHot, verbose=0) print('accuracy=', scores[1]) prediction = model.predict_classes(x_img_test_normalize) plot_images_lables_prediction(x_img_test,y_lable_test,prediction,0,10)