SK Networks Family AI bootcamp 강의노트

29일차 [ CNN, Vgg, ResNet ]

HyunJung_Jo 2025. 2. 25. 17:24

수업자료

https://colab.research.google.com/drive/1VmWo6P8CCaFqPeHnlLw70V4OaypRXNVA#scrollTo=HpLVxmcqj9_a

 

Google Colab Notebook

Run, share, and edit Python notebooks

colab.research.google.com

수업 내용 

  • transforms.Normalize(), transforms.Resize() < 필수
  • kernel size 3이 제일 효과적
  • "Convolution"은 사전적으로 "합성" 또는 "합성 작용"이라는 의미를 갖고 있습니다. 수학적으로는 두 개의 함수나 신호를 결합하여 새로운 신호를 생성하는 연산을 의미합니다. 이 과정에서 한 함수가 다른 함수에 영향을 미치거나, 주어진 신호의 변형을 나타내는 데 사용됩니다.
  • "Stride"의 사전적 의미는 "큰 걸음", "걷다", 또는 "또래나 발걸음"을 의미합니다. 일반적으로는 어떤 방향으로 나아가거나 걸어가는 방식을 설명하는 단어입니다.
  • max pooling - 중요한 것만 뽑아서 피쳐 줄인다. (vs average pooling :중요한 피쳐가 뭉개지는 효과)
  • flatten: 각 데이터간의 관계성, 위치정보 학습 못함
def calculate_norm(dataset):
    # dataset의 axis=1, 2 (height,width) 에 대한 평균 산출
    # axis=(1, 2) specifies that the mean is calculated
    # along the height and width dimensions of the image, 
    # essentially averaging pixel values for each color channel in each image.

    # x -> features(이미지) / _ -> target
    # x -> (color, height, width)
    
    # mean_ -> (dataset_size, color)
    mean_ = np.array([np.mean(x.numpy(), axis=(1, 2)) for x, _ in dataset])
    # r, g, b 채널에 대한 각각의 평균 산출
    mean_r = mean_[:, 0].mean()
    mean_g = mean_[:, 1].mean()
    mean_b = mean_[:, 2].mean()

    # dataset의 axis=1, 2에 대한 표준편차 산출
    # std_ -> (dataset_size, color)
    std_ = np.array([np.std(x.numpy(), axis=(1, 2)) for x, _ in dataset])
    # r, g, b 채널에 대한 각각의 표준편차 산출
    std_r = std_[:, 0].mean()
    std_g = std_[:, 1].mean()
    std_b = std_[:, 2].mean()

    return (mean_r, mean_g, mean_b), (std_r, std_g, std_b)
  • 통계함수는 차원을 없앤다.
train_transform_trivial_augment = transforms.Compose([
    # model의 input size 같아야 함
    transforms.Resize((64, 64)),
    # python을 torch로 형변환
    transforms.ToTensor(),
    # train dataset의 평균과 표준편차 적용
    transforms.Normalize(mean_, std_),
    # Data Augmentation
    transforms.RandomHorizontalFlip(p=0.5), # 좌우 반전..
    transforms.RandomVerticalFlip(p=0.5) # 위아래 반전...
])

test_transform = transforms.Compose([
    # model의 input size 같아야 함
    transforms.Resize((64, 64)),
    # python을 torch로 형변환
    transforms.ToTensor(),
    # train dataset의 평균과 표준편차 적용
    transforms.Normalize(mean_, std_)
])
더보기

이 코드는 이미지 데이터셋에서 RGB 채널별 평균(mean)과 표준편차(standard deviation)를 계산하는 함수입니다. 코드에서 사용된 차원(axis)과 각 계산 과정을 차원 관점에서 설명하겠습니다. NumPy와 텐서 데이터를 다루는 맥락에서 설명하니 참고하세요.

---

### 함수 입력: `dataset`
- `dataset`: 이미지 데이터와 레이블 쌍으로 구성된 데이터셋 (예: PyTorch의 DataLoader나 유사한 구조).
- 각 데이터는 `(x, _)` 형태로, 여기서:
  - `x`: 이미지 데이터 (특징). 차원은 `(color, height, width)`로 가정.
    - `color`: 색상 채널 (RGB라면 3).
    - `height`: 이미지 높이.
    - `width`: 이미지 너비.
  - `_`: 타겟(레이블)으로 여기서는 사용되지 않음.

---

### 1. 평균 계산 (`mean_`)
#### 코드:
```python
mean_ = np.array([np.mean(x.numpy(), axis=(1, 2)) for x, _ in dataset])
```
#### 차원 설명:
- `x.numpy()`: PyTorch 텐서를 NumPy 배열로 변환. 차원은 `(color, height, width)` (예: `(3, H, W)`).
- `np.mean(x.numpy(), axis=(1, 2))`:
  - `axis=(1, 2)`: 높이(`height`, axis 1)와 너비(`width`, axis 2)를 따라 평균을 계산.
  - 이는 각 색상 채널(R, G, B)에 대해 픽셀 값들을 평균낸다는 뜻.
  - 결과: `(color,)` 형태의 배열 (예: `(3,)`), 각 색상 채널의 평균값.
- 리스트 컴프리헨션 `[... for x, _ in dataset]`:
  - 데이터셋의 모든 이미지에 대해 위 과정을 반복.
  - 결과: `(dataset_size, color)` 형태의 배열 (예: `(N, 3)`), 여기서 `N`은 데이터셋 크기.
- `np.array()`: 리스트를 NumPy 배열로 변환.
  - 최종 `mean_` 차원: `(dataset_size, color)`.

#### 의미:
- `mean_`: 데이터셋의 각 이미지마다 RGB 채널별 평균을 계산한 결과.

---

### 2. RGB 채널별 전체 평균 계산
#### 코드:
```python
mean_r = mean_[:, 0].mean()
mean_g = mean_[:, 1].mean()
mean_b = mean_[:, 2].mean()
```
#### 차원 설명:
- `mean_[:, 0]`: `mean_` 배열에서 첫 번째 색상 채널(R)의 모든 이미지에 대한 값 추출.
  - 차원: `(dataset_size,)` (예: `(N,)`).
- `.mean()`: 데이터셋 전체 이미지에 대해 R 채널 평균을 다시 평균냄.
  - 결과: 스칼라 값 (단일 숫자).
- 마찬가지로 `mean_[:, 1]`은 G 채널, `mean_[:, 2]`는 B 채널에 대해 동일 작업 수행.

#### 의미:
- `mean_r`, `mean_g`, `mean_b`: 데이터셋 전체에서 R, G, B 채널 각각의 평균값.

---

### 3. 표준편차 계산 (`std_`)
#### 코드:
```python
std_ = np.array([np.std(x.numpy(), axis=(1, 2)) for x, _ in dataset])
```
#### 차원 설명:
- `np.std(x.numpy(), axis=(1, 2))`:
  - `x.numpy()`: `(color, height, width)` 형태.
  - `axis=(1, 2)`: 높이와 너비를 따라 표준편차 계산.
  - 결과: 각 색상 채널별 표준편차로 `(color,)` 형태의 배열 (예: `(3,)`).
- 리스트 컴프리헨션 `[... for x, _ in dataset]`:
  - 모든 이미지에 대해 계산.
  - 결과: `(dataset_size, color)` 형태 (예: `(N, 3)`).
- `np.array()`: 리스트를 배열로 변환.
  - 최종 `std_` 차원: `(dataset_size, color)`.

#### 의미:
- `std_`: 각 이미지마다 RGB 채널별 표준편차를 계산한 결과.

---

### 4. RGB 채널별 전체 표준편차 계산
#### 코드:
```python
std_r = std_[:, 0].mean()
std_g = std_[:, 1].mean()
std_b = std_[:, 2].mean()
```
#### 차원 설명:
- `std_[:, 0]`: `std_` 배열에서 R 채널의 모든 이미지에 대한 표준편차 추출.
  - 차원: `(dataset_size,)` (예: `(N,)`).
- `.mean()`: 데이터셋 전체 이미지에 대해 R 채널 표준편차의 평균 계산.
  - 결과: 스칼라 값.
- G와 B 채널도 동일.

#### 의미:
- `std_r`, `std_g`, `std_b`: 데이터셋 전체에서 R, G, B 채널 각각의 표준편차 평균.

#### 주의:
- 여기서 `.mean()`을 사용하는 것은 엄밀히 말해 표준편차의 "평균"을 구하는 것으로, 통계적으로는 데이터셋 전체의 표준편차와 다를 수 있음. 보통은 데이터셋 전체 픽셀에 대한 표준편차를 계산해야 하지만, 이 코드는 각 이미지의 표준편차를 평균낸 값임.

---

### 최종 반환값
#### 코드:
```python
return (mean_r, mean_g, mean_b), (std_r, std_g, std_b)
```
- 반환값:
  - `(mean_r, mean_g, mean_b)`: RGB 채널별 평균 튜플.
  - `(std_r, std_g, std_b)`: RGB 채널별 표준편차 평균 튜플.
- 각 값은 스칼라이며, 데이터셋의 정규화(normalization)에 사용 가능.

---

### 차원 요약
1. **입력 `x`**: `(color, height, width)` → 개별 이미지.
2. **`mean_`와 `std_`**: `(dataset_size, color)` → 이미지별 RGB 통계량.
3. **최종 출력**: 스칼라 값들 → 데이터셋 전체의 RGB 평균과 표준편차 평균.

이 함수는 주로 이미지 데이터 전처리(예: 정규화)에서 RGB 채널별 통계값을 구할 때 사용됩니다. 차원에 대한 이해를 바탕으로 코드의 동작을 잘 파악하시길 바랍니다! 추가 질문 있으면 말씀해주세요.

  • data_augmentation: 학습데이터에만 적용, 평가 데이터에는 적용 안한다.
  • normalize는 train,test data 다 할 수 있지만 normalize 할 때 쓰는 평균, 표준편차는 train_data 것만 써야 한다. 
  •  

VGG , ResNet

https://colab.research.google.com/drive/1WP1CScxMWzaTiYbUp6QGOx_mPZVbEfdL

 

Google Colab Notebook

Run, share, and edit Python notebooks

colab.research.google.com

더보기

데이터 로더에서 이미지 데이터가 "color"가 "row" 및 "column"보다 앞서서 배치되는 이유는 주로 채널 우선 순서(Channel First Order)로 데이터를 저장하기 때문입니다. 이 방식은 일반적으로 (배치 크기, 채널 수, 높이, 너비) 순서로 이미지를 표현합니다.

  1. 배치 크기 (Batch Size): 여러 이미지를 한 번에 처리할 수 있도록 묶는 단위.
  2. 채널 수 (Color Channels): RGB 이미지의 경우 3(빨강, 초록, 파랑)이고, 흑백 이미지의 경우 1.
  3. 높이 (Height): 이미지의 세로 픽셀 수.
  4. 너비 (Width): 이미지의 가로 픽셀 수.

이러한 구조는 모델이 채널별로 데이터를 더 효율적으로 처리하고, GPU 연산에 최적화된 방식으로 작동하도록 돕습니다. 다른 배치 순서(예: 높이, 너비, 채널 수)는 때때로 사용할 수 있지만, 많은 프레임워크와 라이브러리에서는 채널 먼저 배치하는 것이 일반적입니다. 궁금한 점이 더 있으시면 말씀해 주세요!

ResNet

  • Residual / 나머지(입력값)를 모델 출력결과와 더하는 것을 반복 => 기울기 소실 방지
  • resnet 레이어 마다 색이 다른 것 > 입력 shape이 다름
  • shortcut 은 입력값들 더해줄 때 shape 맞춰줌
  • skip connection 있는 block unit => BasicBlock
  • resnet 개념이 transformers에도 적용됨

Finetuning

https://colab.research.google.com/drive/1cjBBcNCjSsxkPQUg0uj2HDFY4N8XBzez#scrollTo=yVtrmgcXg_gb

 

Google Colab Notebook

Run, share, and edit Python notebooks

colab.research.google.com

 

 

  • pre-trained model을
    • finetuning(일부 layer parameter 변경) 하거나
    • transfer-learning (전이학습,새로운 데이터셋으로 다시 학습) 하는게 가성비 낫다.

  •  confusion matrix는 무조건 그려봐야 한다.
더보기

Modifying Python's Search Path

content_copy 
import sys

sys.path.append(args.default_path)
Use code with caution
  • import sys: This line imports the sys module, which provides access to some variables used or maintained by the Python interpreter. One of these variables is sys.path, which is a list of directories where Python looks for modules and packages.
  • sys.path.append(args.default_path): This line is adding the directory stored in the variable args.default_path to Python's search path.
  • args.default_path is a variable you would have defined earlier in your notebook to specify the main location of your project or relevant files.
  • Why is this done? This is typically done to help Python locate modules or packages that you've created that reside within your project's structure that are outside of current working directory. By adding your project's root to sys.path, Python can find and import these custom modules without errors.

 

  • model은 i/o만 보면 된다. 안에 레이어 다 볼 필요 없다.
공통 모듈을 만들 때 이쁘게 주석도 달면서 설명을 써줘야 다른 사람들이 가져다 쓰기 좋다.