Usando DEEP LEARNING Para Classificar Defeitos na Fabricação de Chapas Metálicas
Tutorial de classificação usando CNN
- Setup
- Baixando os dados
- EDA
- Dataloader
- Baseline learner (Resnet34)
- Squeezenet Learner
- Squeezenet (artigo)
- ResSqueezeNet (artigo)
!nvidia-smi
!pip install -Uqqq fastai
from google.colab import drive
drive.mount('/content/drive')
!cp /content/drive/MyDrive/Datasets/NEU-CLS.rar NEU_CLS.rar
!unrar x NEU_CLS.rar > /dev/null 2>&1
!ls NEU-CLS
from fastai.vision.all import *
path = Path('NEU-CLS')
path.ls()
img = path.ls()[1]
img = Image.open(img)
img
img.shape
def labeler(o): return o.name.split('_')[0]
labeler(path.ls()[0])
files = get_image_files(path)
files
labels = L(map(labeler, files))
labels
labels.unique()
np.unique(np.array(labels), return_counts=True)
dblock = DataBlock(
blocks = (ImageBlock, CategoryBlock),
get_items = get_image_files,
get_y = labeler,
# batch_tfms = aug_transforms(mult= 1.5, flip_vert=True, max_lighting=0.3),
batch_tfms = [Dihedral(), Flip()],
splitter = RandomSplitter(1/3, seed=42)
)
dls = dblock.dataloaders(path, bs = 64, num_workers = 10)
dls.show_batch()
@patch
@delegates(subplots)
def plot_metrics(self: Recorder, nrows=None, ncols=None, figsize=None, **kwargs):
metrics = np.stack(self.values)
names = self.metric_names[1:-1]
n = len(names) - 1
if nrows is None and ncols is None:
nrows = int(math.sqrt(n))
ncols = int(np.ceil(n / nrows))
elif nrows is None: nrows = int(np.ceil(n / ncols))
elif ncols is None: ncols = int(np.ceil(n / nrows))
figsize = figsize or (ncols * 6, nrows * 4)
fig, axs = subplots(nrows, ncols, figsize=figsize, **kwargs)
axs = [ax if i < n else ax.set_axis_off() for i, ax in enumerate(axs.flatten())][:n]
for i, (name, ax) in enumerate(zip(names, [axs[0]] + axs)):
ax.plot(metrics[:, i], color='#1f77b4' if i == 0 else '#ff7f0e', label='valid' if i > 0 else 'train')
ax.set_title(name if i > 1 else 'losses')
ax.legend(loc='best')
plt.show()
base_learner = cnn_learner(dls, resnet34, metrics = accuracy)
base_learner.fine_tune(10)
base_learner.recorder.plot_metrics()
import torchvision.models as models
squeezenet = models.squeezenet1_0(pretrained=True)
fake_batch = torch.randn((2, 3, 200, 200))
plt.imshow(fake_batch[0].permute(1, 2, 0));
squeezenet(fake_batch).shape
squeezenet.classifier[1] = nn.Conv2d(512, 6, kernel_size=(1, 1), stride=(1, 1))
squeezenet(fake_batch).shape
sqnt_learner = Learner(dls, squeezenet, metrics = accuracy)
sqnt_learner.lr_find()
sqnt_learner.fine_tune(10, 1e-4)
sqnt_learner.recorder.plot_metrics()
sqnt_learner.summary()
base_learner.summary()
dblock = DataBlock(
blocks = (ImageBlock(cls = PILImageBW), CategoryBlock),
get_items = get_image_files,
get_y = labeler,
# batch_tfms = aug_transforms(mult= 1.5, flip_vert=True, max_lighting=0.3),
batch_tfms = [Dihedral(), Flip()],
splitter = RandomSplitter(1/3, seed=42)
)
dls = dblock.dataloaders(path, bs = 64, num_workers = 10)
class Fire(nn.Module):
def __init__(self, inplanes: int, squeeze_planes: int, expand1x1_planes: int, expand3x3_planes: int) -> None:
super(Fire, self).__init__()
self.inplanes = inplanes
self.squeeze = nn.Conv2d(inplanes, squeeze_planes, kernel_size=1)
self.squeeze_activation = nn.ReLU(inplace=True)
self.expand1x1 = nn.Conv2d(squeeze_planes, expand1x1_planes, kernel_size=1)
self.expand1x1_activation = nn.ReLU(inplace=True)
self.expand3x3 = nn.Conv2d(squeeze_planes, expand3x3_planes, kernel_size=3, padding=1)
self.expand3x3_activation = nn.ReLU(inplace=True)
def forward(self, x: torch.Tensor) -> torch.Tensor:
x = self.squeeze_activation(self.squeeze(x))
return torch.cat(
[self.expand1x1_activation(self.expand1x1(x)), self.expand3x3_activation(self.expand3x3(x))], 1
)
num_classes = 6
n_ch = 1
squeezenet_passos = nn.Sequential(
nn.Conv2d(n_ch, 32, kernel_size=7, stride=2),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True),
Fire(32, 4, 16, 16),
Fire(32, 4, 16, 16),
Fire(32, 8, 32, 32),
nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True),
Fire(64, 8, 32, 32),
Fire(64, 12, 48, 48),
Fire(96, 12, 48, 48),
Fire(96, 16, 64, 64),
nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True),
Fire(128, 16, 64, 64),
nn.Dropout(p=0.5),
nn.Conv2d(128, num_classes, kernel_size=1),
nn.ReLU(inplace=True),
nn.AdaptiveAvgPool2d((1, 1)),
nn.Flatten()
)
for m in squeezenet_passos.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_uniform_(m.weight)
if m.bias is not None:
nn.init.constant_(m.bias, 0)
nn.init.normal_(squeezenet_passos[-4].weight, mean=0.0, std=0.01) ;
squeezenet_passos_learner = Learner(dls, squeezenet_passos, metrics = accuracy)
squeezenet_passos_learner.lr_find()
squeezenet_passos_learner.fit_one_cycle(50, 1e-4)
squeezenet_passos_learner.recorder.plot_metrics()
class ResSqueezeNetPassos(nn.Module):
def __init__(self, num_classes: int = 6, dropout: float = 0.5) -> None:
super().__init__()
self.num_classes = num_classes
self.conv1 = nn.Conv2d(1, 32, kernel_size=7, stride=2)
self.mp1 = nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True)
self.f1 = Fire(32, 4, 16, 16)
self.f2 = Fire(32, 4, 16, 16)
self.f3 = Fire(32, 8, 32, 32)
self.mp2 = nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True)
self.f4 = Fire(64, 8, 32, 32)
self.f5 = Fire(64, 12, 48, 48)
self.f6 = Fire(96, 12, 48, 48)
self.f7 = Fire(96, 16, 64, 64)
self.mp3 = nn.MaxPool2d(kernel_size=3, stride=2, ceil_mode=True)
self.f8 = Fire(128, 16, 64, 64)
final_conv = nn.Conv2d(128, self.num_classes, kernel_size=1)
self.classifier = nn.Sequential(
nn.Dropout(p=dropout), final_conv, nn.ReLU(inplace=True), nn.AdaptiveAvgPool2d((1, 1))
)
for m in self.modules():
if isinstance(m, nn.Conv2d):
if m is final_conv:
nn.init.normal_(m.weight, mean=0.0, std=0.01)
else:
nn.init.kaiming_uniform_(m.weight)
if m.bias is not None:
nn.init.constant_(m.bias, 0)
def forward(self, x: torch.Tensor) -> torch.Tensor:
x = nn.Sequential(
self.conv1,
nn.ReLU(inplace=True),
self.mp1,
self.f1
)(x)
x = self.f2(x) + x
x = nn.Sequential(
self.f3,
self.mp2
)(x)
x = self.f4(x) + x
x = self.f5(x)
x = self.f6(x) + x
x = nn.Sequential(
self.f7,
self.mp3
)(x)
x = self.f8(x) + x
x = self.classifier(x)
return torch.flatten(x, 1)
ressqueezenet_passos_learner = Learner(dls, ResSqueezeNetPassos(), metrics = accuracy)
ressqueezenet_passos_learner.fit_one_cycle(100, 3e-4)
ressqueezenet_passos_learner.recorder.plot_metrics()