<jupyter_start><jupyter_text>Train model using ResNet18By using the deep learning library *PyTorch* this page will train the image classifier to detect if the bowl is empty or full.   Imports and unzipping the dataset<jupyter_code>import torch
import torch.optim as optim
import torch.nn.functional as F
import torchvision
import torchvision.datasets as datasets
import torchvision.models as models
import torchvision.transforms as transforms

!unzip -q dataset.zip<jupyter_output>replace dataset/empty/7cbaa6a2-ae92-11ec-bc66-1418c3db55ab.jpg? [y]es, [n]o, [A]ll, [N]one, [r]ename: ^C<jupyter_text>Creating dataset instance<jupyter_code>dataset = datasets.ImageFolder(
    'dataset',
    transforms.Compose([
        transforms.ColorJitter(0.1, 0.1, 0.1, 0.1),
        transforms.Resize((224, 224)),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])
)

# Splitting dataset into train and test sets
train_dataset, test_dataset = torch.utils.data.random_split(dataset, [len(dataset) - 50, 50])<jupyter_output><empty_output><jupyter_text>Creating two data loaders that produces batches of images<jupyter_code>train_loader = torch.utils.data.DataLoader(
    train_dataset,
    batch_size=8,
    shuffle=True,
    num_workers=0,
)

test_loader = torch.utils.data.DataLoader(
    test_dataset,
    batch_size=8,
    shuffle=True,
    num_workers=0,
)<jupyter_output><empty_output><jupyter_text>Using *torchvision* and *resnet18* to define the neural network<jupyter_code>model = models.resnet18(pretrained=True)

# Using only two class labels (empty, full)
model.fc = torch.nn.Linear(512, 2)

device = torch.device('cuda')
model = model.to(device)<jupyter_output><empty_output><jupyter_text>Training the neural networkThis code will train the neural network for 30 epochs (a cycle that runs through all the data). After each epoch it saves the best performing model.<jupyter_code>NR_EPOCHS = 30
MODEL_PATH = 'exmodel.pth'
best_accuracy = 0.0

optimizer = optim.SGD(model.parameters(), lr=0.001, momentum=0.9)

for epoch in range(NR_EPOCHS):
    
    for images, labels in iter(train_loader):
        images = images.to(device)
        labels = labels.to(device)
        optimizer.zero_grad()
        outputs = model(images)
        loss = F.cross_entropy(outputs, labels)
        loss.backward()
        optimizer.step()
    
    test_error_count = 0.0
    for images, labels in iter(test_loader):
        images = images.to(device)
        labels = labels.to(device)
        outputs = model(images)
        test_error_count += float(torch.sum(torch.abs(labels - outputs.argmax(1))))
    
    test_accuracy = 1.0 - float(test_error_count) / float(len(test_dataset))
    print('%d: %f' % (epoch, test_accuracy))
    if test_accuracy > best_accuracy:
        torch.save(model.state_dict(), MODEL_PATH)
        best_accuracy = test_accuracy<jupyter_output>0: 1.000000
1: 0.980000
2: 0.980000
3: 0.980000
4: 0.980000
5: 0.960000
6: 1.000000
7: 0.960000
8: 0.960000
9: 1.000000
10: 1.000000
11: 0.960000
12: 1.000000
13: 1.000000
14: 1.000000
15: 1.000000
16: 1.000000
17: 1.000000
18: 1.000000
19: 1.000000
20: 0.980000
21: 0.960000
22: 0.980000
23: 0.960000
24: 0.980000
25: 1.000000
26: 1.000000
27: 1.000000
28: 0.960000
29: 0.960000
{'fraction_non_alphanumeric': 0.11398176291793313, 'fraction_numerical': 0.1060790273556231, 'mean_word_length': 4.039816232771822, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 20, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '197072', 'license': 'MIT', 'n_tokens_mistral': 1416, 'n_tokens_neox': 1174, 'n_words': 287, 'path': 'train.ipynb', 'repo_name': 'milager/Pet-feeder', 'size': '3290'}