728x90
반응형
5. 데이터 로더 구현하기
def build_dataloader(train_data_dir, val_data_dir):
dataloaders = {}
train_dset = Chest_dataset(train_data_dir, transformer)
# {'train': 데이터...}
dataloaders['train'] = DataLoader(train_dset, batch_size=4, shuffle=True, drop_last=True)
# 트레인 데이터를 4개 씩 섞고 ,drop_last=True 마지막거를 버려라
# {'train' : 데이터...} 담긴 모습
# 각각의 데이터의 특징(웨이트)을 분류하기 위해 4개로 분류하였고 한번에 전부를 돌리는것보단 조금씩 분석을 하면
# 얼마만큼 틀렸거나 최적의 경로를 더 빨리 알 수 있기 때문에 적은 수인 4개 정도로 데이터를 분류하는것이 좋다.
# 251개를 한번에 돌리면 시간이 오래걸리고 반복시에도 시간 문제가 발생한다.
val_dset = Chest_dataset(val_data_dir, transformer)
dataloaders['val'] = DataLoader(val_dset, batch_size=1, shuffle=False, drop_last=False)
return dataloaders
# 트레인 데이터를 4개 씩 섞고 ,drop_last=True 마지막거를 버려라
# {'train' : 데이터...} 담긴 모습
# 각각의 데이터의 특징(웨이트)을 분류하기 위해 4개로 분류하였고 한번에 전부를 돌리는것보단 조금씩 분석을 하면
# 얼마만큼 틀렸거나 최적의 경로를 더 빨리 알 수 있기 때문에 적은 수인 4개 정도로 데이터를 분류하는것이 좋다.
# 251개를 한번에 돌리면 시간이 오래걸리고 반복시에도 시간 문제가 발생한다.
train_data_dir = './Covid19-dataset/train/' # 학습 데이타
val_data_dir = './Covid19-dataset/test/' # 테스트 데이타
dataloaders = build_dataloader(train_data_dir, val_data_dir)
for i, d in enumerate(dataloaders['train']): # 반복 인덱스 값과 데이터 값을 출력을 해보자
print(i, d)
if i == 0:
break
# 출력 결과 한번 반복을 돌경우 4개로 나눴기 때문데 4개의 이미지가 있다.
# target을 최하단부에 보면 섞인 타겟이 4개인것을 알 수 있다.
✔ 결과
0 {'image': tensor([[[[-0.8308, -0.8916, -0.8677, ..., -0.6797, -0.6646, -0.6471],
[-0.8873, -0.8942, -0.9002, ..., -0.6770, -0.6627, -0.6460],
[-0.8754, -0.9074, -0.9250, ..., -0.6893, -0.6627, -0.6432],
...,
[-0.8985, -0.8763, -0.8768, ..., -0.8388, -0.7755, -0.7307],
[-0.8009, -0.8575, -0.8137, ..., -0.8462, -0.9196, -0.7088],
[-0.7368, -0.7897, -0.8608, ..., -0.8182, -0.8737, -0.7346]],
[[-0.8308, -0.8916, -0.8677, ..., -0.6797, -0.6646, -0.6471],
[-0.8873, -0.8942, -0.9002, ..., -0.6770, -0.6627, -0.6460],
[-0.8754, -0.9074, -0.9250, ..., -0.6893, -0.6627, -0.6432],
...,
[-0.8985, -0.8763, -0.8768, ..., -0.8388, -0.7755, -0.7307],
[-0.8009, -0.8575, -0.8137, ..., -0.8462, -0.9196, -0.7088],
[-0.7368, -0.7897, -0.8608, ..., -0.8182, -0.8737, -0.7346]],
[[-0.8308, -0.8916, -0.8677, ..., -0.6797, -0.6646, -0.6471],
[-0.8873, -0.8942, -0.9002, ..., -0.6770, -0.6627, -0.6460],
[-0.8754, -0.9074, -0.9250, ..., -0.6893, -0.6627, -0.6432],
...,
[-0.8985, -0.8763, -0.8768, ..., -0.8388, -0.7755, -0.7307],
[-0.8009, -0.8575, -0.8137, ..., -0.8462, -0.9196, -0.7088],
[-0.7368, -0.7897, -0.8608, ..., -0.8182, -0.8737, -0.7346]]],
[[[-1.0000, -1.0000, -1.0000, ..., 0.9282, 0.5004, -0.9459],
[-1.0000, -1.0000, -1.0000, ..., -0.9413, -0.5848, -0.9731],
[-1.0000, -1.0000, -1.0000, ..., 0.9393, -0.5843, -0.9447],
...,
[-0.9922, -1.0000, -0.9997, ..., -1.0000, -1.0000, -1.0000],
[-0.9870, 0.5032, 0.9987, ..., -1.0000, -1.0000, -1.0000],
[-0.9613, -0.6391, -0.9975, ..., -1.0000, -1.0000, -1.0000]],
[[-1.0000, -1.0000, -1.0000, ..., 0.9282, 0.5004, -0.9459],
[-1.0000, -1.0000, -1.0000, ..., -0.9413, -0.5848, -0.9731],
[-1.0000, -1.0000, -1.0000, ..., 0.9393, -0.5843, -0.9447],
...,
[-0.9922, -1.0000, -0.9997, ..., -1.0000, -1.0000, -1.0000],
[-0.9870, 0.5032, 0.9987, ..., -1.0000, -1.0000, -1.0000],
[-0.9613, -0.6391, -0.9975, ..., -1.0000, -1.0000, -1.0000]],
[[-1.0000, -1.0000, -1.0000, ..., 0.9282, 0.5004, -0.9459],
[-1.0000, -1.0000, -1.0000, ..., -0.9413, -0.5848, -0.9731],
[-1.0000, -1.0000, -1.0000, ..., 0.9393, -0.5843, -0.9447],
...,
[-0.9922, -1.0000, -0.9997, ..., -1.0000, -1.0000, -1.0000],
[-0.9870, 0.5032, 0.9987, ..., -1.0000, -1.0000, -1.0000],
[-0.9613, -0.6391, -0.9975, ..., -1.0000, -1.0000, -1.0000]]],
[[[-0.5189, -0.5431, -0.5126, ..., 0.9880, -0.9370, -0.9115],
[-0.6902, -0.6732, -0.6734, ..., -0.9116, 0.1379, -0.9497],
[-0.6745, -0.6796, -0.6734, ..., -0.9188, -0.8106, -0.8681],
...,
[-0.9923, -0.9955, -1.0000, ..., -1.0000, -1.0000, -1.0000],
[-0.9619, 0.0067, 0.9732, ..., -1.0000, -0.9765, -0.9882],
[ 0.2605, 0.9916, -0.9529, ..., -1.0000, -0.9609, 0.2557]],
[[-0.5189, -0.5431, -0.5126, ..., 0.9880, -0.9370, -0.9115],
[-0.6902, -0.6732, -0.6734, ..., -0.9116, 0.1379, -0.9497],
[-0.6745, -0.6796, -0.6734, ..., -0.9188, -0.8106, -0.8681],
...,
[-0.9923, -0.9955, -1.0000, ..., -1.0000, -1.0000, -1.0000],
[-0.9619, 0.0067, 0.9732, ..., -1.0000, -0.9765, -0.9882],
[ 0.2605, 0.9916, -0.9529, ..., -1.0000, -0.9609, 0.2557]],
[[-0.5189, -0.5431, -0.5126, ..., 0.9880, -0.9370, -0.9115],
[-0.6902, -0.6732, -0.6734, ..., -0.9116, 0.1379, -0.9497],
[-0.6745, -0.6796, -0.6734, ..., -0.9188, -0.8106, -0.8681],
...,
[-0.9923, -0.9955, -1.0000, ..., -1.0000, -1.0000, -1.0000],
[-0.9619, 0.0067, 0.9732, ..., -1.0000, -0.9765, -0.9882],
[ 0.2605, 0.9916, -0.9529, ..., -1.0000, -0.9609, 0.2557]]],
[[[-0.7783, -0.7805, -0.7696, ..., -0.6707, -0.5907, -0.6562],
[-0.5511, -0.6574, -0.7635, ..., -0.6582, -0.6038, -0.6745],
[-0.2294, -0.2396, -0.3251, ..., -0.7919, -0.7370, -0.7647],
...,
[-0.9373, -0.9578, -0.9716, ..., -0.9294, -0.9294, -0.9137],
[-0.9460, -0.9205, -0.9686, ..., -0.9294, -0.8933, -0.8900],
[ 0.2520, -0.9582, -0.9716, ..., -0.9294, -0.9289, 0.2413]],
[[-0.7783, -0.7805, -0.7696, ..., -0.6707, -0.5907, -0.6562],
[-0.5511, -0.6574, -0.7635, ..., -0.6582, -0.6038, -0.6745],
[-0.2294, -0.2396, -0.3251, ..., -0.7919, -0.7370, -0.7647],
...,
[-0.9373, -0.9578, -0.9716, ..., -0.9294, -0.9294, -0.9137],
[-0.9460, -0.9205, -0.9686, ..., -0.9294, -0.8933, -0.8900],
[ 0.2520, -0.9582, -0.9716, ..., -0.9294, -0.9289, 0.2413]],
[[-0.7783, -0.7805, -0.7696, ..., -0.6707, -0.5907, -0.6562],
[-0.5511, -0.6574, -0.7635, ..., -0.6582, -0.6038, -0.6745],
[-0.2294, -0.2396, -0.3251, ..., -0.7919, -0.7370, -0.7647],
...,
[-0.9373, -0.9578, -0.9716, ..., -0.9294, -0.9294, -0.9137],
[-0.9460, -0.9205, -0.9686, ..., -0.9294, -0.8933, -0.8900],
[ 0.2520, -0.9582, -0.9716, ..., -0.9294, -0.9289, 0.2413]]]]), 'target': tensor([[0],
[2],
[2],
[2]])}
# 이제 어떤 모델을 선택해서 데이타를 넣어볼 것인가?!
# 모델을 직접 만들기도 하지만 기존 공개된 모델을 활용을 많이 한다.
# 여러 모델을 여러번 돌려보고 성능이 괜찮은걸 사용한다...
6. VGG19(classification) 모델 불러오기
# pretrained=True: 미리 학습된 weight들을 가지고 옮
# torchvision 의 models 사용...
model = models.vgg19(pretrained=True)
# pytorch 모델을 summary 해주는 모듈
!pip install torchsummary
from torchsummary import summary
# 세이프, 배치사이즈, 디바이스
# param 가중치
summary(model, (3, 224, 224), batch_size=1, device='cuda') # 채널, 세로, 가로, device: cuda or cpu
7. CNN(Convolutional Neural Network)
- 합성곱 인공 신경망
- 전통적인 뉴럴 네트워크 컨볼루셔널 계층을 붙인 형태
- 컨볼루셔널 계층을 통해서 입력 받은 이미지에 대한 특징(Feature)을 추출(전처리)하게 되고 추출한 특징을 기반으로 기존의 뉴럴 네트워크에 이용하여 분류
7-1. CNN을 사용하는 이유
- 영상을 분류할 때 DNN(Deep Neural Network)의 문제점
- 일반적인 DNN은 1차원 형태의 데이터를 사용
- 2차원의 형태의 이미지가 입력되는 경우, flatten 시켜서 한줄로 데이터를 넣음
- 이미지의 공간적/지역적 정보가 손실됨
- DNN의 문제점을 해결하기 위해 고안한 해결책 -> 이미지를 날것(raw input) 그대로 받음으로 공간적/지역적 정보를 유지
7-2. 컨볼루셔널 레이어(Convolutional Layer)
- 입력 데이터로 부터 특징을 추출하는 역할
- 특징을 추출하는 필터(Filter)를 사용함(https://setosa.io/ev/image-kernels/)
- 필터의 값을 비선형 값으로 바꿔주는 액티베이션(Activationi) 함수를 사용
7-3. 풀링
- Feature map의 사이즈를 줄이는 방법
- 데이터의 크기를 줄이고 싶을 때 선택적으로 사용
- max pooling: 사이즈를 점진적으로 줄이는 방법, 선명한 정보만 남겨서 판단과 학습이 쉬워지고 노이즈가 줄어듦
7-4. 패딩(padding)
- CNN 네트워크 특징중 여러 단계에 걸쳐서 계속 필터를 연속적으로 적용하면 필터 적용 후 결과값이 처음에 비해 작아지게 됨 -> 특징이 유실 될 수 있음
- 충분히 특징이 추출되기 전에 결과 값이 작아지지 않도록 패딩 기법을 사용
- 입력값 주위로 0을 넣어서 입력 값의 크기를 인위적으로 키워 결과값이 작아지는 것을 방지
7-5. 스트라이드(Stride)
- 필터를 적용하는 간격(예: 우측으로 한칸씩 아래로 한칸씩 적용)을 설정
- 필터를 적용해서 얻어낸 결과를 Feature map 또는 activation map이라고 부름
7-6. 드룹아웃 레이어(Dropout Layer)
- 오버피팅을 막기 위한 방법
- 뉴럴 네트워크가 학습중일때 랜덤하게 값을 발생하여 학습을 방해함으로 학습용 데이터에 결과가 치우치는 것을 방지함
7-7. FC Layer(Fully Connected Layer)
- 이미지를 분류/설명하기 위해 예측하는 구간
8. 데이터에 맞게 모델 Head 부분을 수정하기
def build_vgg19_based_model(device_name='cpu'):
device = torch.device(device_name)
model = models.vgg19(pretrained=True)
model.avgpool = nn.AdaptiveAvgPool2d(output_size=(1, 1))
model.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(512, 256),
nn.ReLU(),
nn.Linear(256, len(class_list)),
nn.Softmax(dim=1)
)
return model.to(device)
model = build_vgg19_based_model(device_name='cpu')
summary(model, (3, 224, 224), batch_size=1, device='cuda')
✔ 결과
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [1, 64, 224, 224] 1,792
ReLU-2 [1, 64, 224, 224] 0
Conv2d-3 [1, 64, 224, 224] 36,928
ReLU-4 [1, 64, 224, 224] 0
MaxPool2d-5 [1, 64, 112, 112] 0
Conv2d-6 [1, 128, 112, 112] 73,856
ReLU-7 [1, 128, 112, 112] 0
Conv2d-8 [1, 128, 112, 112] 147,584
ReLU-9 [1, 128, 112, 112] 0
MaxPool2d-10 [1, 128, 56, 56] 0
Conv2d-11 [1, 256, 56, 56] 295,168
ReLU-12 [1, 256, 56, 56] 0
Conv2d-13 [1, 256, 56, 56] 590,080
ReLU-14 [1, 256, 56, 56] 0
Conv2d-15 [1, 256, 56, 56] 590,080
ReLU-16 [1, 256, 56, 56] 0
Conv2d-17 [1, 256, 56, 56] 590,080
ReLU-18 [1, 256, 56, 56] 0
MaxPool2d-19 [1, 256, 28, 28] 0
Conv2d-20 [1, 512, 28, 28] 1,180,160
ReLU-21 [1, 512, 28, 28] 0
Conv2d-22 [1, 512, 28, 28] 2,359,808
ReLU-23 [1, 512, 28, 28] 0
Conv2d-24 [1, 512, 28, 28] 2,359,808
ReLU-25 [1, 512, 28, 28] 0
Conv2d-26 [1, 512, 28, 28] 2,359,808
ReLU-27 [1, 512, 28, 28] 0
MaxPool2d-28 [1, 512, 14, 14] 0
Conv2d-29 [1, 512, 14, 14] 2,359,808
ReLU-30 [1, 512, 14, 14] 0
Conv2d-31 [1, 512, 14, 14] 2,359,808
ReLU-32 [1, 512, 14, 14] 0
Conv2d-33 [1, 512, 14, 14] 2,359,808
ReLU-34 [1, 512, 14, 14] 0
Conv2d-35 [1, 512, 14, 14] 2,359,808
ReLU-36 [1, 512, 14, 14] 0
MaxPool2d-37 [1, 512, 7, 7] 0
AdaptiveAvgPool2d-38 [1, 512, 1, 1] 0
Flatten-39 [1, 512] 0
Linear-40 [1, 256] 131,328
ReLU-41 [1, 256] 0
Linear-42 [1, 3] 771
Softmax-43 [1, 3] 0
================================================================
Total params: 20,156,483
Trainable params: 20,156,483
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.57
Forward/backward pass size (MB): 238.31
Params size (MB): 76.89
Estimated Total Size (MB): 315.78
----------------------------------------------------------------
9. 손실함수 불러오기
- input x에 대한 예측값과 실제값 사이의 오차를 계산하는 함수
- cost function: 모든 input dataset에 대하여 계산하는 함수
loss_func = nn.CrossEntropyLoss(reduction='mean')
10. Gradient 최적화 함수 불러오기
optimizer = torch.optim.SGD(model.parameters(), lr=1E-3, momentum=0.9)
10-1. 경사 하강법의 종류
- 배치 경사 하강법
- 가장 기본적인 경사 하강법으로 Vanilla Gradient Descent 라고 부름
- 데이터셋 전체를 고려하여 손실함수를 계산
- 한 번의 Epoch에 모든 파라미터 업데이터를 단 한번만 수행
- Batch의 개수와 lteration은 1이고 Batch size는 전체 데이터의 갯수
- 파라미터 업데이트할 때 전체 데이터셋을 고려하기 때문에 모델 학습시 많은 시간과 메모리가 필요하다는 단점
- 확률적 경사 하강법(Stochastic Gradient Descent)
- 배치 경사 하강법이 모델 학습시 많은 시간과 메모리가 필요하다는 단점을 개선하기 위해 제안된 기법
- Batch size를 1로 설정하여 파라미터를 덥데이트하기 때문에 배치 경사 하강법보다 빠르고 적은 메모리로 학습이 진행
- 중복 데이터를 뽑을 가능성이 있음
- 파라미터 값의 업데이트 폭이 불안정
- 미니 배치 경사 하강법
- Batch size가 1도 아니고 전체 데이터 갯수도 아닌 경우
- 배치 경사 하강법보다 모델 학습 속도가 빠르고, 확률적 경사 하강법보다 안정적인 장점이 있음
- 일반적으로 Batch size를 2의 n제곱에 해당하는 값으로 설정
10-2. 경사 하강법의 알고리즘
- GD(Gradient Descent)
- 모든 데이터를 사용하여 계산하는 방법으로 학습시간이 오래 걸림
- SGD(Stochastic Gradient Descent)
- 확률적 경사 하강법으로 모든 데이터에 대해 가중치를 조절하는 것이 아닌 랜덤으로 일부를 추출해서 가중치를 조절하는 방법
- Momentum
- 관성을 사용하는 방법으로 local minima를 해결하기 위해 고안
- 이전의 방향을 기억하여 관성처럼 추가적인 이동을 하며 local minima 문제를 해결할 확률을 높임
- Adagrad
- 학습률과 관련된 옵티마이저로, Adagrad라는 방식은 변수의 업데이트가 잦을수록 학습률을 조정하는 방식
- RMSprop
- Adagrad은 학습률이 작아지는 문제가 발생
- 위 문제를 해결하기 위해 만들어진 옵티마이저로, 기울기를 단순히 누적하는 것이 아닌 가중이동평균을 사용하여 최근의 기울기에 더 높은 가중치를 두는 방식을 적용한 방법
- Adam(Adaptive Moment Estimation)
- Momentum을 사용
- RMSprop처럼 지수이동평균을 사용하며 학습률을 조정
SGD와 Adam 두개를 최근 많이 사용한다...
반응형
'대학원 시험 공부' 카테고리의 다른 글
운동자세 인식 프로젝트 사전 준비 및 공부 (1) | 2023.04.09 |
---|---|
데이터분석 프로젝트 (파이썬 Covid-19 사진 학습(분류) 3) (0) | 2023.04.05 |
데이터분석 프로젝트(파이썬 Covid-19 사진 학습(분류) 1) (1) | 2023.03.25 |
파이토치 (0) | 2023.02.28 |
텐서플로우 (1) | 2023.02.27 |