文章目錄
-
- 資料集下載下傳連結
- 資料集簡介
- 制作新的train以及val檔案
- 訓練自己的網絡
資料集下載下傳連結
百度網盤下載下傳:
連結: https://pan.baidu.com/s/1Uro6RuEbRGGCQ8iXvF2SAQ 密碼: hl31
資料集簡介
提到Imagenet大家都知道,是一個非常大型、有名的開源資料集。一般設計一個新的分類網絡就會在Imagenet1000類的資料上進行訓練以及驗證。包括常見的目标檢測網絡等,所使用的backbone一般都會先基于Imagenet進行預訓練。但對于普通研究員或者開發者而言,這個資料集太大了(全部下載下傳大概有100GB左右),而且訓練對硬體要求也非常高,通常都是很多塊高端顯示卡并行訓練,即使是這樣的配置通常還要訓練好幾天的時間。是以讓很多人望而卻步(我就是其中之一,關鍵太大,而且國内下載下傳很慢)。
2016年google DeepMind團隊從Imagnet資料集中抽取的一小部分(大小約3GB)制作了Mini-Imagenet資料集,共有100個類别,每個類别都有600張圖檔,共60000張(都是
.jpg
結尾的檔案),而且圖像的大小并不是固定的。
![]() | |
| |
資料集的結構為:
├── mini-imagenet: 資料集根目錄
├── images: 所有的圖檔都存在這個檔案夾中
├── train.csv: 對應訓練集的标簽檔案
├── val.csv: 對應驗證集的标簽檔案
└── test.csv: 對應測試集的标簽檔案
Mini-Imagenet資料集中還包含了
train.csv
、
val.csv
以及
test.csv
三個檔案。需要注意的是,當時作者制作這個資料集時主要是針對小樣本學習領域的,而且提供的标簽檔案并不是從每個類别中進行采樣的。我自己用
pandas
包分析了下每個标簽檔案。
train.csv
包含38400張圖檔,共64個類别。
val.csv
包含9600張圖檔,共16個類别。
test.csv
包含12000張圖檔,共20個類别。
每個标簽檔案之間的圖像以及類别都是互相獨立的,即共60000張圖檔,100個類。
用
pandas
讀取的
csv
檔案資料格式如下,每一行對應一張圖檔的名稱和所屬類别:
filename label
0 n0153282900000005.jpg n01532829
1 n0153282900000006.jpg n01532829
2 n0153282900000007.jpg n01532829
3 n0153282900000010.jpg n01532829
4 n0153282900000014.jpg n01532829
至于每個類别對應的實際物體名稱,可檢視這個json檔案,這個檔案是Imagenet1000類資料中對應的标簽檔案。
{"0": ["n01440764", "tench"],
"1": ["n01443537", "goldfish"],
"2": ["n01484850", "great_white_shark"],
...
}
制作新的train以及val檔案
根據上面分析的,如果想用Mini-Imgenet資料集直接去訓練自己的分類網絡是不可行的,因為
train.csv
和
val.csv
并不是從每個類别中進行采樣的,是以我們需要自己去建構一個新的
train.csv
和
val.csv
檔案。下面是我自己寫的一個建構
train.csv
和
val.csv
标簽檔案的腳本,該腳本會從這100個類别中按給定的比例去劃分訓練集和驗證集。
import os
import json
import pandas as pd
from PIL import Image
import matplotlib.pyplot as plt
def read_csv_classes(csv_dir: str, csv_name: str):
data = pd.read_csv(os.path.join(csv_dir, csv_name))
# print(data.head(1)) # filename, label
label_set = set(data["label"].drop_duplicates().values)
print("{} have {} images and {} classes.".format(csv_name,
data.shape[0],
len(label_set)))
return data, label_set
def calculate_split_info(path: str, label_dict: dict, rate: float = 0.2):
# read all images
image_dir = os.path.join(path, "images")
images_list = [i for i in os.listdir(image_dir) if i.endswith(".jpg")]
print("find {} images in dataset.".format(len(images_list)))
train_data, train_label = read_csv_classes(path, "train.csv")
val_data, val_label = read_csv_classes(path, "val.csv")
test_data, test_label = read_csv_classes(path, "test.csv")
# Union operation
labels = (train_label | val_label | test_label)
labels = list(labels)
labels.sort()
print("all classes: {}".format(len(labels)))
# create classes_name.json
classes_label = dict([(label, [index, label_dict[label]]) for index, label in enumerate(labels)])
json_str = json.dumps(classes_label, indent=4)
with open('classes_name.json', 'w') as json_file:
json_file.write(json_str)
# concat csv data
data = pd.concat([train_data, val_data, test_data], axis=0)
print("total data shape: {}".format(data.shape))
# split data on every classes
num_every_classes = []
split_train_data = []
split_val_data = []
for label in labels:
class_data = data[data["label"] == label]
num_every_classes.append(class_data.shape[0])
# shuffle
shuffle_data = class_data.sample(frac=1, random_state=1)
num_train_sample = int(class_data.shape[0] * (1 - rate))
split_train_data.append(shuffle_data[:num_train_sample])
split_val_data.append(shuffle_data[num_train_sample:])
# imshow
imshow_flag = False
if imshow_flag:
img_name, img_label = shuffle_data.iloc[0].values
img = Image.open(os.path.join(image_dir, img_name))
plt.imshow(img)
plt.title("class: " + classes_label[img_label][1])
plt.show()
# plot classes distribution
plot_flag = False
if plot_flag:
plt.bar(range(1, 101), num_every_classes, align='center')
plt.show()
# concatenate data
new_train_data = pd.concat(split_train_data, axis=0)
new_val_data = pd.concat(split_val_data, axis=0)
# save new csv data
new_train_data.to_csv(os.path.join(path, "new_train.csv"))
new_val_data.to_csv(os.path.join(path, "new_val.csv"))
def main():
data_dir = "/home/wz/mini-imagenet/" # 指向資料集的根目錄
json_path = "./imagenet_class_index.json" # 指向imagenet的索引标簽檔案
# load imagenet labels
label_dict = json.load(open(json_path, "r"))
label_dict = dict([(v[0], v[1]) for k, v in label_dict.items()])
calculate_split_info(data_dir, label_dict)
if __name__ == '__main__':
main()
訓練自己的網絡
項目位址:https://github.com/WZMIAOMIAO/deep-learning-for-image-processing
在
pytorch_classification
->
mini-imagenet
檔案夾中,裡面提供了兩個訓練腳本,一個是針對單GPU的,一個是針對多GPU的。在這個項目中是以訓練ShuffleNetv2為例進行講解的。訓練了100個epoch,達到了78%的準确率。
接着,我拿這個預訓練權重去做遷移學習,訓練其他的小資料集,确實也有一定幫助。在我測試過程中,如果不使用預訓練權重,訓練自己的資料集能達到80%的準确率,如果使用預訓練權重能達到90%的準确率。當然基于Mini-Imagenet的預訓練權重和基于Imagenet的預訓練權重還有一些差距,畢竟資料量擺在這。之前使用基于Imagenet的預訓練權重準确率可以達到94%。
當然,對于自己新搭的網絡,如果想快速驗證一下,Mini-Imagenet也是一個不錯的選擇。