<jupyter_start><jupyter_text>Notwendige Importe<jupyter_code>import torch
from torch import nn
from torch import optim
from torchvision import transforms, datasets, models
from torch.utils.data import DataLoader
from torch.utils.data.sampler import SubsetRandomSampler

import numpy as np
import matplotlib.pyplot as plt

%matplotlib inline<jupyter_output><empty_output><jupyter_text>Daten laden und vorbereiten<jupyter_code># data path
data_dir = 'flowers'
# number of subprocesses to use for data loading
num_workers = 0
# how many samples per batch to load
batch_size = 32
# percentage of training set to use as validation
valid_size = 0.2

# Define transforms for the training data and testing data
train_transforms = transforms.Compose([
                                       transforms.RandomRotation(30),
                                       transforms.RandomResizedCrop(224),
                                       transforms.RandomHorizontalFlip(),
                                       transforms.ToTensor()
                                      ]) 

test_transforms = transforms.Compose([
                                      transforms.Resize(255),
                                      transforms.CenterCrop(224),
                                      transforms.ToTensor()
                                    ])


# Pass transforms in here, then run the next cell to see how the transforms look
train_data = datasets.ImageFolder(data_dir + '/train', transform=train_transforms)
test_data = datasets.ImageFolder(data_dir + '/test', transform=test_transforms)

# obtain training indices that will be used for validation
num_train = len(train_data)
indices = list(range(num_train))
np.random.shuffle(indices)
split = int(np.floor(valid_size * num_train))
train_idx, valid_idx = indices[split:], indices[:split]

# define samplers for obtaining training and validation batches
train_sampler = SubsetRandomSampler(train_idx)
valid_sampler = SubsetRandomSampler(valid_idx)

# prepare data loaders (combine dataset and sampler)
train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size,
    sampler=train_sampler, num_workers=num_workers)
valid_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, 
    sampler=valid_sampler, num_workers=num_workers)
test_loader = torch.utils.data.DataLoader(test_data, batch_size=batch_size, 
    num_workers=num_workers)
len(train_data)+len(test_data)<jupyter_output><empty_output><jupyter_text>Zeigt einige Beispielbilder aus vorbereiteten Daten<jupyter_code># specify the image classes
classes = ['gut', 'durstig']

# obtain one batch of training images
dataiter = iter(train_loader)
images, labels = dataiter.next()
# images = images.numpy() # convert images to numpy for display

# plot the images in the batch, along with the corresponding labels
fig = plt.figure(figsize=(25, 4))
# display 20 images
for idx in np.arange(20):
    ax = fig.add_subplot(2, 10, idx+1, xticks=[], yticks=[])
    plt.imshow(np.transpose(images[idx], (1, 2, 0)))  # convert from Tensor image
    ax.set_title(classes[labels[idx]])<jupyter_output><empty_output><jupyter_text>Hier sehen wir Beispiele für gute und durstige Blumen  Vor Trainiertes Modell herunterladen und anzeigendensenet121 wird mit Tausend verschiedener Bilder trainiert. Es gibt auch Fotos von Blumen darin. Aber wir haben das Modell für durstige Blumen trainiert.<jupyter_code>model = models.densenet121(pretrained=True)
# model<jupyter_output><empty_output><jupyter_text>Frieren Sie vortrainierte Modelle ein<jupyter_code>for param in model.parameters():
    param.requires_grad = False<jupyter_output><empty_output><jupyter_text>Den Klassifikator des vortrainierten Modells für unser Projekt Ändern<jupyter_code>device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    
model.classifier = nn.Sequential(nn.Linear(1024, 256),
                                 nn.ReLU(),
                                 nn.Dropout(0.2),
                                 nn.Linear(256, 2),
                                 nn.LogSoftmax(dim=1))

criterion = nn.NLLLoss()
optimizer = optim.Adam(model.classifier.parameters(), lr=0.003)

model.to(device);<jupyter_output><empty_output><jupyter_text>Trainiere Model<jupyter_code>epochs = 10
steps = 0
running_loss = 0
print_every = 10

valid_loss_average_min = np.Inf

for epoch in range(epochs):    
    valid_loss_average = 0.0 
    for inputs, labels in train_loader:
        steps += 1        
        inputs, labels = inputs.to(device), labels.to(device)        
        optimizer.zero_grad()        
        logps = model.forward(inputs)
        loss = criterion(logps, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()        
        if steps % print_every == 0:
            valid_loss = 0
            accuracy = 0
            model.eval()            
            with torch.no_grad():
                for inputs, labels in valid_loader:
                    inputs, labels = inputs.to(device), labels.to(device)
                    logps = model.forward(inputs)
                    batch_loss = criterion(logps, labels)                    
                    valid_loss += batch_loss.item()                   
                    ps = torch.exp(logps)
                    top_p, top_class = ps.topk(1, dim=1)
                    equals = top_class == labels.view(*top_class.shape)
                    accuracy += torch.mean(equals.type(torch.FloatTensor)).item() 
            valid_loss_average = valid_loss/len(valid_loader)
            print(f"Epoch {epoch+1}/{epochs}.. "
                  f"Train loss: {running_loss/print_every:.3f}.. "
                  f"Valid loss: {valid_loss_average:.3f}.. "
                  f"Valid accuracy: {accuracy/len(valid_loader):.3f}")
            running_loss = 0
            model.train()
            if valid_loss_average < valid_loss_average_min:
                print('Valid loss decreased ({:.6f} --> {:.6f}).  Saving model ...'
                      .format(valid_loss_average_min, valid_loss_average))
                torch.save(model.state_dict(), 'transferlearning_model.pt')
                valid_loss_average_min = valid_loss_average<jupyter_output><empty_output><jupyter_text>Lade Model<jupyter_code>model.load_state_dict(torch.load('transferlearning_model.pt', 
                                 map_location=torch.device('cpu')
                                )
                     )<jupyter_output><empty_output><jupyter_text>Prüfe Das ModelWir zeigen dem Model während des Trainings keine Testfotos<jupyter_code># track test loss
test_loss = 0.0
class_correct = list(0. for i in range(2))
class_total = list(0. for i in range(2))

model.eval()
# iterate over test data
for data, target in test_loader:
    # move tensors to GPU if CUDA is available
    data, target = data.to(device), target.to(device)
    # forward pass: compute predicted outputs by passing inputs to the model
    output = model(data)
    # calculate the batch loss
    loss = criterion(output, target)
    # update test loss 
    test_loss += loss.item()*data.size(0)
    # convert output probabilities to predicted class
    _, pred = torch.max(output, 1)
    # compare predictions to true label
    correct_tensor = pred.eq(target.data.view_as(pred))
    correct = np.squeeze(correct_tensor.numpy()) if device == "cpu" else np.squeeze(correct_tensor.cpu().numpy())
    # calculate test accuracy for each object class
    for i in range(data.size(0)):
        label = target.data[i]
        class_correct[label] += correct[i].item()
        class_total[label] += 1
# average test loss
test_loss = test_loss/len(test_loader.dataset)
print('Test Loss: {:.6f}\n'.format(test_loss))

for i in range(2):
    if class_total[i] > 0:
        print('Test Accuracy of %5s: %2d%% (%2d/%2d)' % (
            classes[i], 100 * class_correct[i] / class_total[i],
            np.sum(class_correct[i]), np.sum(class_total[i])))
    else:
        print('Test Accuracy of %5s: N/A (no training examples)' % (classes[i]))

print('\nTest Accuracy (Overall): %2d%% (%2d/%2d)' % (
    100. * np.sum(class_correct) / np.sum(class_total),
    np.sum(class_correct), np.sum(class_total)))<jupyter_output>Test Loss: 0.234589

Test Accuracy of   gut: 96% (32/33)
Test Accuracy of durstig: 93% (31/33)

Test Accuracy (Overall): 95% (63/66)<jupyter_text>Teste das Modell manuell<jupyter_code>from PIL import Image

class_names = ['good', 'thirsty']

def predict_plant_situation(img):
    # Check if it's a array of picture or a path of picture
    if isinstance(img, str):        
        # load the image from path
        img = Image.open(img, mode='r')
    else:
        # convert image array in to PIL image
        img = Image.fromarray(img)
    # normalize picture    
    img_transform = transforms.Compose([
#                                         transforms.Resize(255),
#                                         transforms.CenterCrop(224),
                                        transforms.ToTensor()
                                        ])
    img = img_transform(img)
    # reshape the picture for the model
    img = img.reshape((1, img.shape[0], img.shape[1], img.shape[2]))    
    # pass the picture from model
    model.eval()
    output = model(img)
    # if you want to use index of pred
    _, pred = torch.max(output, 1)
    # if you want to use label 
#     pred = class_names[np.squeeze(output.data.max(1, keepdim=True)[1])]         
    print(output)
    return pred
import cv2
import time
# take a picture from webcam
def get_image(camera=0):
    cap = cv2.VideoCapture(camera)
    cap.set(3,640) # adjust width
    cap.set(4,480) # adjust height
    time.sleep(4)
    success, img = cap.read()
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    cap.release()
    plt.imshow(img)
    return img
def get_plant_situation(camera=0, path=0):
    if path==0:
        # get an image from webcam
        img = get_image(camera)
    else:
        # get an image from folder
        img = path
    return predict_plant_situation(img).numpy()[0]
# img_path = r"C:\Users\Sahin\Documents\GitHub\equal_project\flowers\test\good\healthy_070.jpg"  # 0
# img_path = r"C:\Users\Sahin\Documents\GitHub\equal_project\flowers\test\thirsty\wilted_166.jpg"  # 1

# 1:durstig 0:gut
# get_plant_situation(path=img_path)
get_plant_situation()<jupyter_output>tensor([[-1.3401, -0.3036]], grad_fn=<LogSoftmaxBackward>)
{'fraction_non_alphanumeric': 0.10251506168117051, 'fraction_numerical': 0.017117720187434255, 'mean_word_length': 2.686288332745858, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 20, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '281107', 'license': 'MIT', 'n_tokens_mistral': 3370, 'n_tokens_neox': 3196, 'n_words': 759, 'path': 'Laboratory for Plant Thirst Classification with Transfer Learning.ipynb', 'repo_name': 'coder52/equal_project', 'size': '10457'}