PytorchCNNプロジェクトの構築3 --- Cifar10データセットの処理

全体的なコード私のgithubで見ることができます

  • 画像処理に関する実際の畳み込みニューラルネットワーク実験では、データセットではなく画像自体を直接扱うことが多いため、画像をデータセットに変換してトレーニングする方法を学ぶ必要があります。今日の主なコンテンツは変換です。画像おなじみのデータセットに変換します〜

  • 例としてCifar10データセットを取り上げます。最初に公式WebサイトからCifar10データセットをダウンロードし、次にデータセットを画像に変換し、次に画像をデータセットに変換します。


準備:

実験装置の説明:

  • 私はリモートサーバー、pycharmプログラミングを使用しています
  • 最初にPytorchCNNフォルダーを作成すると、後続のすべてのファイルとフォルダーがこのファイルに含まれます。

1.公式ウェブサイトからCifar10データセットをダウンロードします

Cifar10データセットには、50,000枚のトレーニング画像と10,000枚のテスト画像を含む合計60,000枚の画像があり、各画像は3 * 32 * 32(3チャネル、画像サイズは32 * 32)です。

Cifar10の公式Webサイトを開き、Visionから必要なパーツをダウンロードしてから、公式Webサイトのチュートリアルに従って、その後の圧縮プロセスを学習します。

ここに画像の説明を挿入
ここに画像の説明を挿入

注意:

  • データセットは比較的大きいため、データセットをルートディレクトリにダウンロードし、使用するたびに直接呼び出すことをお勧めします。これにより、スペースを節約できます。Cifar10をルートディレクトリ「/ DATASET / Cifar10 /」に配置しました
  • データセットには、data_batch_1、data_batch_2、…、data_batch_5、test_batchの合計6つのファイルが含まれていることがわかります。各バッチには10,000枚の画像が含まれています。以下は各ファイルのプロセスです。

2.トレーニングセットを画像に変換し、画像のパスと名前をtxtファイルに保存し、一定の確率に従ってトレーニングセットをトレーニングデータセットと検証データセットに分割します。

'''seg dataset to pic'''
def Trainset2Pic(cfg):
    classes = ('airplane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    valid_pic_txt = open(cfg.PARA.cifar10_paths.valid_data_txt, 'w')# 设置为‘w'模式,并且放在最开始,则每次进行时,都会清空重写。
    train_pic_txt = open(cfg.PARA.cifar10_paths.train_data_txt, 'w')
    for i in range(1, 6):
        label_batch = ('A', 'B', 'C', 'D', 'E')
        traindata_file = os.path.join(cfg.PARA.cifar10_paths.original_trainset_path, 'data_batch_' + str(i))
        with open(traindata_file, 'rb') as f:
            train_dict = pkl.load(f,encoding='bytes')  # encoding=bytes ,latin1,train_dict为字典,包括四个标签值:b'batch_label',b'labels',b'data',b'filenames'
            data_train = np.array(train_dict[b'data']).reshape(10000, 3, 32, 32)
            label_train = np.array(train_dict[b'labels'])
            num_val = int(data_train.shape[0]*cfg.PARA.cifar10_paths.validation_rate)#验证集的个数

            val_list = random.sample(list(range(0,int(data_train.shape[0]))), num_val)

        for j in range(10000):
            imgs = data_train[j]
            r = Image.fromarray(imgs[0])
            g = Image.fromarray(imgs[1])
            b = Image.fromarray(imgs[2])
            img = Image.merge("RGB", (b, g, r))

            picname_valid = cfg.PARA.cifar10_paths.after_validset_path + classes[label_train[j]] + label_batch[i - 1] + str("%05d" % j) + '.png'
            picname_train = cfg.PARA.cifar10_paths.after_trainset_path + classes[label_train[j]] + label_batch[i - 1] + str("%05d" % j) + '.png'

            if (j in val_list):#如果在随机选取的验证集列表中,则保存到验证集的文件夹下
                img.save(picname_valid)
                valid_pic_txt.write(picname_valid + ' ' + str(label_train[j]) + '\n')

            else:
                img.save(picname_train)
                train_pic_txt.write(picname_train + ' ' + str(label_train[j]) + '\n')

    valid_pic_txt.close()
    train_pic_txt.close()

3.テストセットtest_datasetも同じ処理を行います

def Testset2Pic(cfg):
    classes = ('airplane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    testdata_file = os.path.join(cfg.PARA.cifar10_paths.original_testset_path, 'test_batch')
    test_pic_txt = open(cfg.PARA.cifar10_paths.test_data_txt, 'w')
    with open(testdata_file, 'rb') as f:
        test_dict = pkl.load(f, encoding='bytes')  # train_dict为字典,包括四个标签值:b'batch_label',b'labels',b'data',b'filenames'
        data_test = np.array(test_dict[b'data']).reshape(10000, 3, 32, 32)
        label_test= np.array(test_dict[b'labels'])

    test_pic_txt = open(cfg.PARA.cifar10_paths.test_data_txt, 'a')
    for j in range(10000):
        imgs = data_test[j]

        r = Image.fromarray(imgs[0])
        g = Image.fromarray(imgs[1])
        b = Image.fromarray(imgs[2])
        img = Image.merge("RGB", [b, g, r])

        picname_test = cfg.PARA.cifar10_paths.after_testset_path + classes[label_test[j]] + 'F' + str("%05d" % j) + '.png'
        img.save(picname_test)
        test_pic_txt.write(picname_test + ' ' + str(label_test[j]) + '\n')
    test_pic_txt.close()

説明:

写真が処理された後、対応するtxtファイルと、対応するデータセットの写真がDATASET / cifar10フォルダーに保存されているフォルダーを確認できます。

ここに画像の説明を挿入

ここに画像の説明を挿入
ここに画像の説明を挿入


4.次に、画像をデータセットに変換し、torch.utils.data.Datasetクラスを継承して書き込みます

'''3. pic to dataset'''
from torch.utils.data import Dataset
class Cifar10Dataset(Dataset):
    def __init__(self,txt,transform):
        super(Cifar10Dataset,self).__init__()
        fh = open(txt, 'r')
        imgs = []
        for line in fh:
            line = line.strip('\n')
            words = line.split()  # 用split将该行切片成列表
            imgs.append((words[0], int(words[1])))
        self.imgs = imgs
        self.transform = transform

    def __getitem__(self, index):
        file_path, label = self.imgs[index]
        label = ToOnehot(label,10)
        img = Image.open(file_path).convert('RGB')
        if self.transform is not None:
            Trans = DataPreProcess(img)
            if self.transform == 'for_train' or 'for_valid':
                img = Trans.transform_train()
            elif self.transform == 'for_test':
                img = Trans.transform_test()
        return img,label

    def __len__(self):
        return len(self.imgs)

5.画像データを処理します

class DataPreProcess():
    def __init__(self,img):
        self.img = img

    def transform_train(self):
        return transforms.Compose([
            transforms.RandomCrop(32, padding=4),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
            transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),#三个均值,三个方差。
        ])(self.img)

    def transform_test(self):
        return transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
        ])(self.img)

説明:

画像データ処理には標準化された操作、つまり0-1の正規化があり、その後のトレーニングは収束しやすいのですが、なぜこれらの数値なのですか?画像を元に計算してみよう〜

class Normalization():
    def __init__(self):
        super(Normalization, self).__init__()

    def Mean_Std(self, file_path):#计算所有图片的均值和方差
        MEAN_B, MEAN_G, MEAN_R = 0, 0, 0
        STD_B, STD_G, STD_R = 0, 0, 0
        count = 0
        with open(file_path, 'r') as f:
            for line in f.readlines():
                count += 1
                words = line.strip('\n').split()
                img = torch.from_numpy(cv2.imread(words[0])).float()
                MEAN_B += torch.mean(img[:, :, 0] / 255)
                MEAN_G += torch.mean(img[:, :, 1] / 255)
                MEAN_R += torch.mean(img[:, :, 2] / 255)
                STD_B += torch.std(img[:, :, 0] / 255)
                STD_G += torch.std(img[:, :, 1] / 255)
                STD_R += torch.std(img[:, :, 2] / 255)
        MEAN_B, MEAN_G, MEAN_R = MEAN_B / count, MEAN_G / count, MEAN_R / count
        STD_B, STD_G, STD_R = STD_B / count, STD_G / count, STD_R / count
        return (MEAN_B, MEAN_G, MEAN_R), (STD_B, STD_G, STD_R)

    def Normal(self,img, mean, std):#将一张图片,由正态分布变成0-1分布
        img = img/255
        img = img.transpose(2, 0, 1) #[H,W,C]-->[C,H,W],与pytorch的ToTensor做相同的变换,便于比较
        img[0, :, :] =  (img[0, :, :] - mean[0]) / std[0]
        img[1, :, :] =  (img[1, :, :] - mean[1]) / std[1]
        img[2, :, :] =  (img[2, :, :] - mean[2]) / std[2]
        return img


def test():
    img = cv2.imread('../../DATASET/cifar10/trainset/airplaneA00029.png')#读取一张图片,cv读取结果为[b,g,r] [H,W,C]
    my_normal = Normalization()
    img1 = my_normal.Normal(img, (0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
    normal = transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))

    converToTensor = transforms.ToTensor()
    img2 = converToTensor(img) #[H,W,C]-->[C,H,W]
    img2 = normal(img2)
    print(img1)
    print(img2)

if __name__ == '__main__':
    test()

参照

Cifar10公式サイト

最後に、プロジェクト全体の構築を教えてくれた兄と研究室で一緒に勉強してくれた小さな友達に感謝します〜彼らがすべてに成功し、素晴らしい未来を迎えることを願っています!

おすすめ

転載: blog.csdn.net/qq_44783177/article/details/113747416