71.5% (88/123일)
고양이와 강아지의 이미지를 분류하는 DNN 모델을 만들고 활성화 함수를 sigmoid와 ReLU를 각각 사용했을 때와 성능이 월등하게 좋은 CNN 모델의 적용하여 결과 확인
데이터 셋 링크: https://www.kaggle.com/datasets/uciml/mushroom-classification
실습을 위해 사용할 데이터 셋은 강아지와 고양이 이미지 데이터 셋 구조로서 train과 test 폴더 하위에 고양이와 강아지 이미지가 있으며, labels에는 각 이미지 파일 경로와 라벨이 담겨있다. 라벨은 고양이는 0, 강아지는 1이다.
cats_and_dogs
├── test
│ ├── cats
│ ├── dogs
│ └── label.csv
└── train
├── cats
├── dogs
└── label.csv
데이터를 구분 짓는 과정을 반복하여 최적의 구분선을 도출해 내며, 출력과 실제 수치 간의 오차를 계산해서 각 레이어의 가중치를 최적싱태로 조절하는 기법, 오류역전파(backpropagation)
가중치와 편향을 조정하여 입력 데이터를 출력 데이터로 매핑하는 방식으로, 이 과정은 비선형적인 변환을 수행하며, 각 은닉층은 입력 데이터의 새로운 특징을 추출함
2개 이상의 은닉층 존재히고, 망이 복잡한 경우 시간이 오래 걸리며, 결과가 일정하지 않을 수 있으며, 가중치의 의미를 정확하게 해석하기 어려움
1) 범위:
2) 기울기 소실 문제:
3) 비선형성:
4) 학습 속도:
시그모이드는 출력값을 0과 1 사이의 범위로 제한해야 하는 분류 문제에 적합할 수 있고, ReLU는 깊은 신경망에서 학습 속도를 향상시키고 기울기 소실 문제를 방지하는 데 유용할 수 있음
1) 디바이스 일치: 모델, 데이터, 레이블을 같은 디바이스(CPU, GPU - CUDA)
2) 메모리 관리: 대용량 데이터 처리 시
3) 손실함수와 옵티마이저 설정: 모델과 데이터에 맞는 함수 선택, loss function, CrossEntropyLoss, MSELoss, Adam, SGD, learning rate etc.
4) 모델의 올바른 입력 차원: 모델에 맞는 입력 크기를 확인, 입력 데이터의 차원과 실제 데이터의 차원이 일치 여부
5) 배치 사이즈 관리: 너무 크면 메모리 초과, 너무 작으면 학습 속도 느림
6) 텐서를 NumPy 배열로 변환하려면 반드시 .cpu()
를 사용해야 함
콜랩에서 압축파일 풀기
!unzip "./drive/MyDrive/multicampus/cats_and_dogs.zip" -d "/content"
CustomImageDataset 클래스
. torch.utils.data.Dataset 클래스를 상속받아서 init, len, getitem 3개의 메서드를 구현
. init: 클래스 초기화 메서드, 이미지 데이터셋의 경로와 변환 함수 (transform)를 인자로 받으며, CSV 파일을 로드하여 이미지 파일 경로와 레이블을 저장함
len: 데이터셋의 총 샘플 수를 반환하는 메서드, 즉, CSV 파일의 행 수를 반환함
getitem: 인덱스로 데이터셋에서 샘플을 가져오는 메서드, 인덱스에 해당하는 이미지 파일 경로와 레이블을 가져오며, 이미지를 로드하고 변환 함수를 적용한 후, 이미지와 레이블을 튜플로 반환함. 이미지 데이터셋을 생성하고, 변환 함수를 적용하여 데이터를 전처리할 수 있음
입력 데이터 : train data 8,000마리, test data 2,000마리
len(train_dataset), len(test_dataset)
(8000, 2000)
이미지 전처리 변환 정의
transforms.Resize(224, 224),
img, label = train_dataset[4500]
plt.imshow(img.numpy().transpose(1, 2 ,0), cmap="Greys")
img, label = train_dataset[4500]
plt.imshow(img.numpy().transpose(1, 2 ,0), cmap="Pastel1")
plot_img_tensor(train_dataset[254][0])
batch_size = 128 #--> 32, 64, 128, 256 변경test
train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_dataloader = DataLoader(test_dataset, batch_size=batch_size, shuffle=True)
batch.shape, labels.shape
(torch.Size([32, 3, 224, 224]), torch.Size([32]))
SingleLayerPerceptron(
(fc): Linear(in_features=150528, out_features=10, bias=True)
(softmax): Softmax(dim=1)
)
MultiLayerPerceptron(
(fc1): Linear(in_features=150528, out_features=50, bias=True)
(fc2): Linear(in_features=50, out_features=10, bias=True)
(activation): Sigmoid()
)
하이퍼 파라미터 셋팅
learning_rate = 0.001
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
criterion = torch.nn.CrossEntropyLoss()
epochs = 10
weights = ResNet18_Weights.IMAGENET1K_V1
transform = weights.transforms()
train_dataset = CustomImageDataset("./cats_and_dogs/train", transform=transform)
test_dataset = CustomImageDataset("./cats_and_dogs/test", transform=transform)
-(3, 224, 224) 크기로 입력 이미지를 Resize한 다음, 정규화를 통해 소수로 변환시켜 줌
Strategy 1: pretrained 모델을 가져와 전체 레이어들을 fine-tuning하는 방법
Strategy 2: 일부 Convolution Layer와 Fully Connected Layer를 학습시키는 방식
Strategy 3: 마지막 Fully Connected Layer만 학습시키는 방식
model = resnet18(weights=weights)
model.fc = torch.nn.Linear(in_features=512, out_features=2)
model = model.to(device)
learning_rate = 0.001
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
learning_rate = 0.002
learning_rate = 0.00001
learning_rate = 0.001
learning_rate = 0.002
learning_rate = 0.00001
learning_rate = 0.001
learning_rate = 0.002
learning_rate = 0.00001
cats and dogs 이미지 데이터 10,000건(train_data 8,000건, test_data 2,000건)을 DNN 및 CNN 모델 학습과정에서 validation data의 accuracy가 DNN에서는 50% 전후 였으나, CNN모델에서 95~98%의 월등한 정확성을 나타내었음
DNN모델에서 batch size를 128, 32로 learning rate를 0.001, 0.0001로 적용해 본 결과 Multilayer Perceptron, Vanishing Gradient, ReLU에서는 정확도가 50% 전후로 별 상이함이 없었으나, single모델에서 32, 0.0001로 설정했을 때 55%~61% 다소 높았음
CNN모델에서는 4가지 전략을 학습한 결과, Strategy 2와 Strategy 3가 각각 97% 이상 높은 성능을 보였으며, Strategy 3이 98%로 좋은 결과가 나타났음.
CNN모델에서는 4가지 전략에서 learning rate를 각각 0.001, 0.002, 0.000001로 변경하여 적용 결과, 0.001이 성능이 가장 좋았음