티스토리 뷰

728x90

www.dacon.io/competitions/open/235596/overview/

 

[이미지] MNIST : 숫자 이미지 분류

출처 : DACON - Data Science Competition

dacon.io


1. Dataset 구축

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
class DatasetMnist(data.Dataset):
    def __init__(self,file_path,test_mode=False,train=True,transform=None):
        self.file_path=file_path
        self.test_mode=test_mode
        self.train=train
        self.transform=transform
        data=pd.read_csv(self.file_path,index_col='index')
        self.dataframe=list(data.values)
 
        image=[]
        label=[]
        if test_mode==False :
            #Train -> Get train.csv -> train,vali data
            train_len=int(len(self.dataframe)*0.8)
            if self.train :
                #Train
                for idx in range(0,train_len):
                    label.append(self.dataframe[idx][0])
                    image.append(self.dataframe[idx][1:])
                self.labels=np.asarray(label)
                self.images=np.asarray(image).reshape(-1,28,28,1).astype('float32')
            else :
                #Vali
                for idx in range(train_len,len(self.dataframe)):
                    label.append(self.dataframe[idx][0])
                    image.append(self.dataframe[idx][1:])
                self.labels=np.asarray(label)
                self.images=np.asarray(image).reshape(-1,28,28,1).astype('float32')
        else :
            # Final Test Mode = (Train + Vali)-> ALL Train / Test data(No label) -> Test data
            if self.train :
                for line in self.dataframe :
                    label.append(line[0])
                    image.append(line[1:])
                self.labels=np.asarray(label)
                self.images=np.asarray(image).reshape(-1,28,28,1).astype('float32')
            else :
                for line in self.dataframe :
                    label.append(0)
                    image.append(line[0:])
                self.labels=np.asarray(label)
                self.images=np.asarray(image).reshape(-1,28,28,1).astype('float32')
    
    def __len__(self):
        return len(self.images)
    
    def __getitem__(self,index):
        label=self.labels[index]
        image=self.images[index]
        if self.transform != None:
            image=self.transform(image)
        return image,label
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class AddGaussianNoise(object):
    def __init__(self, mean=0., std=1.):
        self.std = std
        self.mean = mean
        
    def __call__(self, tensor):
        return tensor + torch.randn(tensor.size()) * self.std + self.mean
    
    def __repr__(self):
        return self.__class__.__name__ + '(mean={0}, std={1})'.format(self.mean, self.std)
 
def get_data():
    rgb_mean = (0.5,)
    rgb_std = (0.5,)
    train_transforms=transforms.Compose([transforms.ToTensor(),
                                        transforms.RandomHorizontalFlip(),
                                        transforms.Normalize(rgb_mean,rgb_std),
                                        transforms.RandomApply([AddGaussianNoise(0.,1.)],p=0.5)])
    vali_transforms=transforms.Compose([transforms.ToTensor(),
                                        transforms.Normalize(rgb_mean,rgb_std)])
    #train_data=DatasetMnist('./datasets/train.csv',test_mode=False,train=True,transform=train_transforms)
    train_data=DatasetMnist('./datasets/train.csv',test_mode=True,train=True,transform=train_transforms)
    vali_data=DatasetMnist('./datasets/train.csv',test_mode=False,train=False,transform=vali_transforms)
    test_data=DatasetMnist('./datasets/test.csv',test_mode=True,train=False,transform=vali_transforms)
    train_iter=torch.utils.data.DataLoader(train_data,batch_size=BATCH_SIZE,shuffle=True,num_workers=1)
    vali_iter=torch.utils.data.DataLoader(vali_data,batch_size=BATCH_SIZE,shuffle=True,num_workers=1)
    test_iter=torch.utils.data.DataLoader(test_data,batch_size=BATCH_SIZE,shuffle=False,num_workers=1)
    return train_iter,vali_iter,test_iter
cs

2. Model 설계 및 구축

A Model : Normal Linear

B Model : Normal CNN

C Model : f(x)+x CNN

 

EnsembleModel = A+B+C -> Softmax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import torch
import torch.nn as nn
import torch.nn.functional as F
 
class EnsembleModel(nn.Module):
    def __init__(self,Model_A,Model_B,Model_C):
        super(EnsembleModel,self).__init__()
        self.Model_A=Model_A
        self.Model_B=Model_B
        self.Model_C=Model_C
        self.init_params()
 
    def forward(self,x1,x2,x3):
        x1=self.Model_A(x1)
        x2=self.Model_B(x2)
        x3=self.Model_C(x3)
        x=x1+x2+x3
        return F.log_softmax(x,dim=1)
 
    def init_params(self) :
        for m in self.modules() :
            if isinstance(m,nn.Conv2d) :
                nn.init.kaiming_normal_(m.weight)
                nn.init.zeros_(m.bias)
            elif isinstance(m,nn.Linear) :
                nn.init.kaiming_normal_(m.weight)
                nn.init.zeros_(m.bias)
            elif isinstance(m,nn.BatchNorm2d) :
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)
 
class LinearModel(nn.Module): 
    # only linear model
    def __init__(self,in_channel=28*28,linear_channel=[256,64,32,10]):
        super(LinearModel,self).__init__()
        self.in_channel=in_channel
        self.linear_channel=linear_channel
        layers=[]
        prev_channel=in_channel
        for current_channel in linear_channel :
            layers.append(nn.Linear(in_features=prev_channel,
                                    out_features=current_channel,bias=True))
            layers.append(nn.BatchNorm1d(current_channel))
            layers.append(nn.ReLU(inplace=True))
            prev_channel=current_channel
        self.net=nn.Sequential(*layers)
    
    def forward(self,x):
        x=self.net(x)
        return F.log_softmax(x,dim=1)
 
class CnnModel(nn.Module):
    # Normal CNN
    def __init__(self,image_size=[28,28],in_channel=1,hidden_channel=[32,64,32,10]):
        super(CnnModel,self).__init__()
        self.image_size=image_size
        self.in_channel=in_channel
        self.hidden_channel=hidden_channel
        self.kernel_size=3
        layers=[]
        prev_channel=in_channel
        # 28 -> 14 -> 7 -> 3 -> 1
        for current_channel in hidden_channel :
            layers.append(nn.Conv2d(in_channels=prev_channel,
                                    out_channels=current_channel,
                                    kernel_size=self.kernel_size,
                                    stride=(1,1),
                                    padding=((self.kernel_size-1)//2)))
            layers.append(nn.BatchNorm2d(current_channel))
            layers.append(nn.ReLU(True))
            layers.append(nn.MaxPool2d(kernel_size=(2,2),stride=(2,2)))
            prev_channel=current_channel
        self.net=nn.Sequential(*layers)
    
    def forward(self,x):
        x=self.net(x)
        x=x.reshape(-1,10)
        return F.log_softmax(x,dim=1)
        
class CustomModel(nn.Module):
    # Custom Model (like Resnet)
    def __init__(self,image_size=[28,28],in_channel=1,block1_channel=[64,32,64],block2_channel=[64,32,64],out_channel=10):
        super(CustomModel,self).__init__()
        self.image_size=image_size
        self.kernel_size=3
        self.in_channel=in_channel
        self.block1_channel=block1_channel
        self.block2_channel=block2_channel
        self.out_channel=out_channel
        self.MaxPool_net=nn.MaxPool2d(kernel_size=(2,2),stride=(2,2))
        # Start layers (imagesize=28->14)
        start_layers=[]
        start_layers.append(nn.Conv2d(in_channels=self.in_channel,
                                    out_channels=self.block1_channel[0],
                                    kernel_size=self.kernel_size,
                                    stride=(1,1),
                                    padding=((self.kernel_size-1)//2)))
        start_layers.append(nn.BatchNorm2d(self.block1_channel[0]))
        start_layers.append(nn.ReLU(True))
        start_layers.append(nn.MaxPool2d(kernel_size=(2,2),stride=(2,2)))
 
        self.start_net=nn.Sequential(*start_layers)
 
        #Block1 layers ( 14->7)
        block1_layers=[]
        prev_channel=self.block1_channel[0]
        for current_channel in block1_channel:
            block1_layers.append(nn.Conv2d(in_channels=prev_channel,
                                    out_channels=current_channel,
                                    kernel_size=self.kernel_size,
                                    stride=(1,1),
                                    padding=((self.kernel_size-1)//2)))
            block1_layers.append(nn.BatchNorm2d(current_channel))
            block1_layers.append(nn.ReLU(True))
            prev_channel=current_channel
        
        self.block1_net=nn.Sequential(*block1_layers)
 
        #Block2 layers (7->3)
        block2_layers=[]
        for current_channel in block2_channel:
            block2_layers.append(nn.Conv2d(in_channels=prev_channel,
                                    out_channels=current_channel,
                                    kernel_size=self.kernel_size,
                                    stride=(1,1),
                                    padding=((self.kernel_size-1)//2)))
            block2_layers.append(nn.BatchNorm2d(current_channel))
            block2_layers.append(nn.ReLU(True))
            prev_channel=current_channel
        
        self.block2_net=nn.Sequential(*block2_layers)
 
        #output layers
        output_layers=[]
        output_layers.append(nn.Conv2d(in_channels=prev_channel,
                                    out_channels=out_channel,
                                    kernel_size=self.kernel_size,
                                    stride=(1,1)))
        output_layers.append(nn.BatchNorm2d(out_channel))
        output_layers.append(nn.ReLU(True))
 
        self.output_net=nn.Sequential(*output_layers)
 
    def forward(self,x):
        x=self.start_net(x) # 14
        identity=x
        x=self.block1_net(x)+identity
        x=self.MaxPool_net(x) # 7
        identity=x
        x=self.block2_net(x)+identity
        x=self.MaxPool_net(x) # 3
        x=self.output_net(x)
        x=x.view(-1,10)
        return F.log_softmax(x,dim=1)
cs

 

3. 결과

전체 소스코드는 github.com/hunmin-hub/DL_Tutorial/tree/main/DACON_Mnist

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함