소개: CNN이 세상을 보는 방법
Le CNN(컨벌루션 신경망) 그들은 컴퓨터 비전에 혁명을 일으켰고 초인적인 정확도로 이미지를 자동으로 인식하는 것이 가능해졌습니다. 완전히 연결된 네트워크와 달리 CNN은 공간 구조 데이터: 인접한 픽셀은 상관되는 경향이 있으며 로컬 패턴(가장자리, 텍스처)이 반복됩니다. 이미지의 다른 위치에 있습니다.
CNN의 핵심 아이디어와 운영 회선: 필터(커널)가 흐른다 로컬 특징을 추출하여 이미지에 추가합니다. 네트워크는 계층별로 계층 구조를 구축합니다. 점점 더 추상적인 특징: 단순한 가장자리부터 복잡한 모양, 완전한 개체까지.
무엇을 배울 것인가
- 컨볼루션 작업: 커널, 스트라이드, 패딩
- 풀링: 차원 축소 및 위치 불변
- 역사적 아키텍처: LeNet, AlexNet, VGG, ResNet
- 딥 네트워크에서 연결 건너뛰기 및 그래디언트 소실 문제
- 전이 학습: ImageNet에서 사전 훈련된 모델 재사용
- 모델의 견고성을 향상시키기 위한 데이터 확대
- 훈련과 평가를 통해 PyTorch에서 완전한 구현
컨볼루션 작업
CNN의 심장과 컨벌루션 레이어. 작은 필터(커널), 일반적으로 크기가 3x3 또는 5x5이며 요소별 계산을 이미지 위로 스크롤합니다. 필터와 기본 이미지 부분 사이의 요소입니다. 결과는 하나 기능 맵 이는 각 위치에서 특정 패턴의 존재를 강조합니다.
두 개의 매개변수가 컨볼루션 동작을 제어합니다.
- 보폭: 커널이 움직이는 속도. Stride=1은 동일한 크기의 특징 맵을 생성하고, stride=2는 크기를 절반으로 줄입니다.
- Padding: 이미지 가장자리에 0을 추가합니다. "동일" 패딩은 원래 크기를 유지하고 "유효" 패딩은 크기를 줄입니다.
import torch
import torch.nn as nn
# Convoluzione 2D: 3 canali input (RGB), 16 filtri output, kernel 3x3
conv_layer = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3,
stride=1, padding=1)
# Input: batch di 4 immagini RGB 32x32
x = torch.randn(4, 3, 32, 32)
output = conv_layer(x)
print(f"Input shape: {x.shape}") # [4, 3, 32, 32]
print(f"Output shape: {output.shape}") # [4, 16, 32, 32]
# Con stride=2 e padding=1
conv_stride2 = nn.Conv2d(3, 16, kernel_size=3, stride=2, padding=1)
output_s2 = conv_stride2(x)
print(f"Stride 2 output: {output_s2.shape}") # [4, 16, 16, 16]
풀링: 차원 축소
컨볼루션 이후의 레이어는 풀링 공간적 차원을 줄인다. 기능 맵을 사용하면 매개변수 수와 계산 비용이 줄어듭니다. 풀링은 또한의 한 형태 번역 불변성: 물체의 작은 움직임 이미지에서 추출된 특징은 변경되지 않습니다.
두 가지 주요 유형은 다음과 같습니다.
- 최대 풀링: 각 창에서 최대값을 선택합니다. 가장 두드러진 특징을 유지하며 가장 많이 사용되는 유형입니다.
- 평균 풀링: 각 창의 평균을 계산합니다. 일반적으로 출력 전에 사용되는 보다 부드러운 기능을 생성합니다.
CNN이 잘 작동하는 이유
CNN은 이미지의 세 가지 기본 속성을 활용합니다. 소재지 (기능 중요한 것은 지역적입니다), 부담 공유 (동일한 필터가 모든 곳에 적용됩니다. 매개 변수를 대폭 줄임) e 번역 불변성 (고양이 그리고 이미지 중앙과 모서리에 고양이가 있습니다). 이러한 속성은 CNN 주문을 생성합니다. 공간적으로 구조화된 데이터의 경우 완전히 연결된 네트워크보다 크기가 더 효율적입니다.
역사적 아키텍처: LeNet에서 ResNet까지
LeNet-5 (1998)
필기 숫자 인식을 위해 Yann LeCun이 설계한 르넷-5 그리고 최초의 성공적인 CNN. 단 5개의 레이어(컨볼루션 2개 + 완전 연결 3개)를 사용하여 다음을 보여줍니다. 컨벌루션 네트워크는 기존의 기능 엔지니어링 방법을 능가할 수 있습니다.
VGG (2014)
VGGNet 나는 깊이가 중요하다는 것을 증명합니다: 독점적으로 스택된 3x3 커널을 사용합니다. 16 또는 19개 레이어에서 ImageNet에서 뛰어난 성능을 달성했습니다. 시퀀스 커버에 3x3 필터 2개 5x5 필터와 동일한 수용 필드이지만 매개변수가 적고 비선형성이 더 높습니다.
레스넷(2015)
레스넷 (Residual Network)는 매우 깊은 네트워크를 훈련시키는 문제를 해결했습니다. 그들과 함께 연결 건너뛰기: 직접 변환 F(x)를 학습하는 대신, 각각 블록은 잔차 차이 F(x) + x를 학습합니다. 이렇게 하면 그라데이션이 직접 흐를 수 있습니다. 여러 계층에 걸쳐 152개 이상의 계층으로 네트워크를 훈련할 수 있습니다.
import torch
import torch.nn as nn
class ResidualBlock(nn.Module):
"""Blocco residuo base di ResNet"""
def __init__(self, channels):
super().__init__()
self.conv1 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
self.bn1 = nn.BatchNorm2d(channels)
self.conv2 = nn.Conv2d(channels, channels, kernel_size=3, padding=1)
self.bn2 = nn.BatchNorm2d(channels)
self.relu = nn.ReLU(inplace=True)
def forward(self, x):
identity = x # Skip connection
out = self.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
out += identity # Residual: F(x) + x
return self.relu(out)
class SimpleCNN(nn.Module):
"""CNN per classificazione CIFAR-10"""
def __init__(self, num_classes=10):
super().__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 32, kernel_size=3, padding=1),
nn.BatchNorm2d(32),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2), # 32x32 -> 16x16
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
nn.MaxPool2d(2, 2), # 16x16 -> 8x8
nn.Conv2d(64, 128, kernel_size=3, padding=1),
nn.BatchNorm2d(128),
nn.ReLU(inplace=True),
nn.AdaptiveAvgPool2d((1, 1)) # 8x8 -> 1x1
)
self.classifier = nn.Linear(128, num_classes)
def forward(self, x):
x = self.features(x)
x = x.view(x.size(0), -1)
return self.classifier(x)
model = SimpleCNN()
x = torch.randn(8, 3, 32, 32)
print(f"Output: {model(x).shape}") # [8, 10]
전이 학습: 사전 훈련된 모델 재사용
대규모 데이터 세트에 대해 처음부터 CNN을 훈련하려면 엄청난 계산 리소스가 필요합니다. 그만큼 전이 학습 이 문제를 해결합니다. 사전 훈련된 모델을 사용합니다. 대규모 데이터세트(일반적으로 1,400만 개의 이미지가 포함된 ImageNet)를 기반으로 자신만의 방식으로 조정 특정 작업.
가장 일반적인 전략은 두 단계로 구성됩니다.
- 특징 추출: 사전 훈련된 모델의 가중치는 동결되고 최종 분류기만 대체됩니다.
- 미세 조정: 일부 상위 계층은 해동되어 매우 낮은 학습률로 재학습됩니다.
import torchvision.models as models
# Caricare ResNet50 pre-addestrato su ImageNet
model = models.resnet50(weights=models.ResNet50_Weights.DEFAULT)
# Congelare tutti i parametri
for param in model.parameters():
param.requires_grad = False
# Sostituire il classificatore finale per 5 classi
num_features = model.fc.in_features
model.fc = nn.Sequential(
nn.Dropout(0.3),
nn.Linear(num_features, 256),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(256, 5) # 5 classi custom
)
# Solo i parametri del nuovo classificatore saranno addestrati
trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)
total = sum(p.numel() for p in model.parameters())
print(f"Trainable: {trainable:,} / {total:,} parametri")
데이터 증강: 변환을 통한 견고성
La 데이터 증대 인위적으로 강화된 정규화 기술 이미지에 무작위 변환을 적용하여 훈련 데이터세트의 다양성을 높입니다. 회전, 절단, 수평 뒤집기 및 색상 변형을 통해 네트워크에 불변 이러한 변화에.
from torchvision import transforms
# Pipeline di data augmentation per training
train_transform = transforms.Compose([
transforms.RandomResizedCrop(224, scale=(0.8, 1.0)),
transforms.RandomHorizontalFlip(p=0.5),
transforms.RandomRotation(15),
transforms.ColorJitter(brightness=0.2, contrast=0.2,
saturation=0.2, hue=0.1),
transforms.RandomAffine(degrees=0, translate=(0.1, 0.1)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225]),
transforms.RandomErasing(p=0.1)
])
# Per validation/test: solo resize e normalize
val_transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],
[0.229, 0.224, 0.225])
])
시리즈의 다음 단계
- 다음 기사에서는 순환 신경망(RNN) 및 LSTM 시퀀스 처리를 위해
- LSTM이 어떻게 사라지는 그래디언트를 해결하고 시간적 종속성을 모델화하는지 살펴보겠습니다.
- 감성 분석 및 텍스트 생성 모델을 구현하겠습니다.







