Zephyrnet-logo

Drie computervisieprojecten om uw datawetenschapscarrière omhoog te schieten!

Datum:

Dit artikel is gepubliceerd als onderdeel van het Data Science-blogathon

De meeste mensen, wanneer ze beginnen met het leren van Data Science en Machine Learning, raken vaak verveeld als ze niet de kans krijgen om met interessante code te spelen in een aantal real-life projecten waar ze kunnen werken aan verschillende stadia van de pijplijn van de Data Science Levenscyclus van projecten.

Dus in dit artikel heb ik 3 Data Science- of Machine Learning-projecten met Code uitgelegd. Deze projecten zijn geschikt voor zowel Data Science Beginners als Practitioners, waar ze kunnen proberen deze projecten te implementeren en hun handen vuil kunnen maken aan de implementatie van het Data Science-project.

  • Face Image Generation met behulp van Deep Convolutional Generative Adversarial Networks (DCGAN) met Pytorch
  • Ontwikkel en implementeer een gezichtsmaskerdetectiesysteem met OpenCV, Keras en StreamLit
  • Beeldruis verwijderen met behulp van AutoEncoders (Encoder-Decoder-netwerk) en U-Net-architectuur met Keras

Laten we beginnen met de eerste:

Face Image Generation met behulp van Deep Convolutional Generative Adversarial Networks (DCGAN) met Pytorch

GAN

Figuur met de architectuur van Generatief Adversarieel Netwerk (GAN)

Afbeelding 1 

In dit project trainen we een Deep Convolutioneel Generatief Adversarial Network (DCGAN) model op de CelebFaces-attributen (CelebA) dataset met als doel een generatornetwerk te krijgen dat ons helpt om nieuwe afbeeldingen van menselijke gezichten te maken die er zo echt mogelijk uitzien. Als je de benodigde dataset wilt downloaden, gebruik dan deze link.

Om meer te weten te komen over de theorie achter de GAN en DCGAN, kun je dit raadplegen: dit artikel

In het kort kunnen we de GAN op de volgende manier definiëren:

GAN's kunnen worden opgevat als een twee spelers (dwz Generator en Discriminator) niet-coöperatief spel, waarbij elke speler de bijbehorende kostenfunctie wil minimaliseren.

Koppel de Google Drive in Google Colab

van google.colab schijf importeren drive.mount('/content/drive')

In dit project gebruiken we de CelebFaces Attributen Dataset (CelebA) waarin de afbeelding is bijgesneden, wat uiteindelijk resulteert in het verwijderen van delen van de afbeelding die geen gezicht bevatten, en daarna gebeurde het formaat wijzigen in een grootte van 64x64x3 dimensie NumPy-afbeelding.

De verwerkte-CelebA-small zip uitpakken

!unzip "/content/drive/MyDrive/processed-celeba-small.zip"

Geef de Data-directory

data_dir = 'processed_celeba_small/'

Noodzakelijke afhankelijkheden of bibliotheken importeren

importeer numpy als np importeer matplotlib.pyplot als plt importeer augurk als pkl %matplotlib inline

Visualiseer de CelebA-gegevens

Deze dataset bevat meer dan 200,000 afbeeldingen van beroemdheden met aantekeningen of labels. Deze afbeeldingen zijn in feite kleurenafbeeldingen die elk 3 kleurkanalen (RGB) hebben. In x- en y-dimensies moeten afbeeldingen een vierkante Tensor van grootte hebben (afbeeldingsgrootte x afbeeldingsgrootte).

! pip install torch torchvision

Importeer noodzakelijke modules van Pytorch

importeer torch uit torchvision importeer datasets uit torchvision importeer transformaties

Batch neuraal netwerk met behulp van data loader

Om nu toegang te krijgen tot de afbeeldingen in batches, maken we een Gegevenslader.

def get_dataloader(batch_size, image_size, data_dir='processed_celeba_small/'): transform = transforms.Compose([transforms.Resize(image_size),transforms.ToTensor()]) image_dataset = datasets.ImageFolder(data_dir, transform = transform) return torch .utils.data.DataLoader (image_dataset, batch_size = batch_size, shuffle = True)

DataLoader Hyperparameters

  • U kunt elke redelijke kiezen: seriegrootte parameter op basis van uw eigen.
  • Echter, uw afbeeldingsgrootte moet 32 ​​zijn. Als we het formaat van de gegevens wijzigen, gebeurt het dat de kleinere afbeelding (minder aantal pixels) leidt tot een snellere training van het model, terwijl er nog steeds overtuigende afbeeldingen van gezichten worden gemaakt.
batch_size = 64 # hyperparameter img_size = 32 # dataloader met batch_size en img_size celeba_train_loader = get_dataloader(batch_size, img_size)

De Tensor-afbeeldingen converteren naar het NumPy-type en vervolgens de dimensie transponeren om de afbeelding weer te geven

def imshow(img): npimg = img.numpy() plt.imshow(np.transpose(npimg, (1, 2, 0))) dataiter = iter(celeba_train_loader) afbeeldingen, _ = dataiter.next() # Het plotten van de afbeeldingen uit een batch fig = plt.figure(figsize=(20,4)) plot_size=20 voor idx in np.arange(plot_size): ax = fig.add_subplot(2, plot_size/2, idx+1, xticks=[ ], yticks=[]) imshow(afbeeldingen[idx])

Output:

uitvoer | Computer Vision-projecten

De afbeelding schalen naar een bereik van -1 tot 1 (aanname - invoer x wordt geschaald van 0-1)

Nu voordat u begint met de modeldefinitie, we zullen een functie schrijven om de afbeeldingsgegevens te schalen naar een pixelbereik van -1 tot 1 die we tijdens de training zullen gebruiken. We doen dit omdat de uitvoer van een hyperbolische tangens-geactiveerde generator pixelwaarden zal bevatten in een bereik van -1 tot 1, en we moeten onze trainingsafbeeldingen herschalen in het bereik van [-1,1] zoals nu, ze zijn in het bereik 0-1.

def scale(x, feature_range=(-1, 1)): min , max = feature_range x = x * (max - min) + min return x
img = afbeeldingen[0] scaled_img = scale(img) print('Min: ', scaled_img.min()) # controleer of het bereik van de geschaalde img ongeveer -1 tot 1 is print('Max: ', scaled_img.max ())

Het model definiëren

Een GAN bestaat uit twee vijandige netwerken, een discriminator en een generator respectievelijk.

discriminator

De discriminator is een convolutionele classifier zonder max-pooling-lagen. De invoer naar de discriminator zijn 32x32x3 tensorbeelden en de uitvoer resulteert in een enkele waarde die aangeeft dat het beeld echt of nep is.

import torch.nn als nn import torch.nn.functioneel als F
def conv (in_channels, out_channels, kernel_size, stride=2, padding=1, batch_norm = True): layers =[] layers.append(nn.Conv2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, bias= False)) if (batch_norm): layers.append(nn.BatchNorm2d(out_channels)) return nn.Sequentiële(*lagen)
class Discriminator(nn.Module): def __init__(self, conv_dim): """ conv_dim - Diepte van eerste convolutionele laag """ super(Discriminator, self).__init__() self.conv_dim =conv_dim self.conv1 = conv ( 3, conv_dim, 4, batch_norm= False) # 3 conv-laag gevolgd door volledig verbonden laag self.conv2 = conv (conv_dim, conv_dim*2, 4) self.conv3 = conv (conv_dim*2, conv_dim*4, 4) self.fc = nn.Linear(conv_dim*4*4*4, 1) def forward(self, x): """ x - De invoer naar het neurale netwerk retourneert de discriminator logits (output) """ y = F .leaky_relu(self.conv1(x), 0.2) y = F.leaky_relu(self.conv2(y), 0.2) y = F.leaky_relu(self.conv3(y), 0.2) out = y.view(-1 , self.conv_dim*4*4*4) # flattening out = self.fc(out) # output layer return out

Generator

Dit onderdeel van de GAN leert nepgegevens te creëren door feedback van de discriminator op te nemen en de discriminator te helpen de echte output te classificeren. Dit onderdeel van het netwerk helpt ons om de invoer te upsamplen en een nieuw beeld te genereren van dezelfde grootte als onze trainingsgegevens 32x32x3. De ingangen zijn vectoren van enige lengte z_maat terwijl de uitvoer een afbeelding is met de vorm 32x32x3.

def deconv (in_channels, out_channels, kernel_size, stride=2, padding=1, batch_norm = True): layers =[] layers.append(nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=stride, padding=padding, bias= False)) if(batch_norm): layers.append(nn.BatchNorm2d(out_channels)) return nn.Sequentiële(*lagen)
class Generator(nn.Module): def __init__(self, z_size, conv_dim): """ z_size - Lengte van de latente invoervector z conv_dim - Diepte van de invoer naar de lats transponeer conv-laag """ super(Generator, zelf ).__init__() self.conv_dim = conv_dim self.fc2 = nn.Linear(z_size, conv_dim*4*4*4) self.t_conv1 = deconv (conv_dim*4, conv_dim*2, 4) self.t_conv2 = deconv ( conv_dim*2, conv_dim, 4) self.t_conv3 = deconv (conv_dim, 3, 4, batch_norm= False) def forward(self, x): """ x - input output - 32x32x3 tensor afbeelding """ y = self. fc2(x) y = y.view(-1,self.conv_dim*4, 4,4) z = F.relu(self.t_conv1(y)) z = F.relu(self.t_conv2(z)) z = torch.tanh(self.t_conv3(z)) return z

Gewichtsinitialisatie

Om de modellen zo snel mogelijk te laten convergeren, hebben we de gewichten van de convolutionele en lineaire lagen in het model geïnitialiseerd op basis van de origineel DCGAN-papier, waarop staat - "Alle gewichten zijn geïnitialiseerd vanuit een nul-gecentreerde normale verdeling met een standaarddeviatie van 0.02"

def weights_init_normal(m): """ Gewichten worden verkregen uit N(0,0.02) distributie m: laag """ classname = m.__class__.__name__ if hasattr(m, 'weight') en classname.find('Conv' ) of classname.find('Lineair') != -1: m.weight.data.normal_(0.0, 0.02) m.bias.data.fill_(0)

Het complete netwerk bouwen

Om ons netwerk te bouwen, zullen we de modelhyperparameters definiëren en de discriminator en generator instantiëren uit de klassen gedefinieerd in de Model definiëren pagina.

# instantiëren de discriminator en generator def complete_network(d_conv_dim, g_conv_dim, z_size): D = Discriminator(d_conv_dim) G = Generator(z_size=z_size, conv_dim=g_conv_dim) D.apply(weights_init_normal) # initialize the model weights (initialize the model weights(z_size=z_size, conv_dim=g_conv_dim) ) print(D) print(G) retour D, G

# model hyperparameter d_conv_dim = 64 g_conv_dim = 64 z_size = 100 D, G = compleet_network(d_conv_dim, g_conv_dim, z_size)
import torch train_on_gpu = torch.cuda.is_available() if not train_on_gpu: # om de training op GPU te verzekeren indien beschikbaar print('No GPU') else: print('GPU Available.Training...')

Verliesberekening - discriminator en generatief verlies

discriminator – Totaal verlies = loss_real-image + loss_fake-image Voor Discriminator is de uitvoer 1 voor echt beeld en 0 voor nepbeeld. Generator Loss zorgt ervoor dat de discriminator een echt beeld produceert.

def real_loss(D_out): ''' D_out - discriminator logits output real loss ''' batch_size = D_out.size(0) labels = torch.ones(batch_size)*0.9 # eenzijdige label smoothing if train_on_gpu: labels = labels.cuda () criterium = nn.BCEWithLogitsLoss() # binaire kruis-entropie met logits verlies verlies = criterium (D_out.squeeze(), labels) # verliesberekening retourverlies def fake_loss(D_out): ''' D_out: discriminator logits output - nep loss ''' batch_size = D_out.size(0) labels = torch.zeros(batch_size) # neplabels = 0 if train_on_gpu: labels = labels.cuda() criterium = nn.BCEWithLogitsLoss() loss = criterium(D_out.squeeze( ), labels) # verliesberekening retourverlies

import torch.optim as optim # params lr_d = 0.0002 lr_g = 0.0002 beta1= 0.5 beta2=0.999 #default # Adam Optimizers gebruiken d_optimizer = optim.Adam(D.parameters(), lr_d, [beta1, beta2]) g_optimizer = optim. Adam(G.parameters(), lr_g, [beta1, beta2])

Model opleiding

Tijdens de training wisselen we z/w discriminator en generator af. Hier gebruiken we de echt_verlies en nep_verlies functies om de verliezen voor Discriminator en Generator te berekenen.

  • Train eerst de discriminator door af te wisselen tussen echte en nepbeelden van menselijke gezichten
  • Dan probeert de generatorcomponent de discriminator te misleiden en zou een tegengestelde verliesfunctie moeten hebben
def train(D, G, n_epochs, print_every=50): ''' D - het discriminatornetwerk G - het generatornetwerk n_epochs - aantal tijdperken print_every - interval om de output van de modellen te printen en vast te leggen - D en G loss '' ' if train_on_gpu: D.cuda() G.cuda() # verlies en gegenereerde "nep" monsterverliezen = [] monsters = [] # gegevens voor bemonstering zijn vast - ze zijn constant tijdens de training # Help ook bij het inspecteren van de prestaties van het model sample_size=16 fixed_z = np.random.uniform(-1, 1, size=(sample_size, z_size)) fixed_z = torch.from_numpy(fixed_z).float() if train_on_gpu: fixed_z = fixed_z.cuda() voor tijdperk binnen bereik (n_epochs): #epoch voor batch_i, (real_images, _) in enumerate(celeba_train_loader): # batch train loop batch_size = real_images.size(0) real_images = scale(real_images) if train_on_gpu: real_images = real_images.cuda() d_optimizer. zero_grad() if train_on_gpu: real_images = real_images.cuda() out_real = D(real_images) d_loss_real = real_loss(out_real) z = np.random.uniform(-1, 1, size=(batch _size, z_size)) z = torch.from_numpy(z).float() if train_on_gpu: z = z.cuda() fake_out =G(z) out_fake = D(fake_out) d_loss_fake = fake_loss(out_fake) d_loss = d_loss_real + d_loss_fake d_loss.backward() d_optimizer.step() g_optimizer.zero_grad() z = np.random.uniform(-1, 1, size=(batch_size, z_size)) z = torch.from_numpy(z).float() if train_on_gpu : z = z.cuda() fake_out_g = G(z) G_D_out = D(fake_out_g) g_loss = real_loss(G_D_out) g_loss.backward() g_optimizer.step() if (batch_i % print_every == 0): loss.append( (d_loss.item(), g_loss.item())) # voeg D en G loss toe # print de statistieken print('Epoch [{:5d}/{:5d}] | d_loss: {:6.4f} | g_loss: {:6.4f}'.format(epoch+1, n_epochs, d_loss.item(), g_loss.item())) G.eval() # genereer samples samples_z = G(fixed_z) samples.append(samples_z) G.train() met open('train_samples.pkl', 'wb') als f: #pkl bestand pkl.dump(samples, f) retourverliezen

n_epochs = 30 # aantal tijdperkverliezen = trein (D, G, n_epochs=n_epochs) #Training

Het verlies van de discriminator en generator na elk tijdperk uitzetten

fig, ax = plt.subplots() verliezen = np.array(verliezen) plt.plot(losses.T[0], label='Discriminator') plt.plot(losses.T[1], label='Generator' ) plt.title("Treinverlies") plt.legend()

Output:

Verliesplot | Computer Vision-projecten

Genereer voorbeeld van training

# Bekijk lijst van doorgegeven van voorbeelden def view_samples(epoch, samples): fig, axes = plt.subplots(figsize=(20,4), nrows=2, ncols=8, sharex=True,sharey=True) voor ax, img in zip(axes.flatten(), samples[epoch]): img = img.detach().cpu().numpy() img = np.transpose(img, (1, 2, 0)) img = ( (img + 1)*255 / (2)).astype(np.uint8) ax.xaxis.set_visible(False) ax.yaxis.set_visible(False) im = ax.imshow(img.reshape((32,32,3, XNUMX)))
met open('train_samples.pkl', 'rb') als f: samples = pkl.load(f) v_s = view_samples(-1, samples)

Output:

uitvoer | Computer Vision-projecten

Conclusie

Door de uitvoer te zien, kunt u zien dat ons model in staat was om nieuwe afbeeldingen van nep-mensengezichten te genereren die er zo realistisch mogelijk uitzien. Ook zijn alle afbeeldingen lichter van schaduw, zelfs de bruine gezichten zijn wat lichter. Dit komt omdat de CelebA dataset is enigszins bevooroordeeld omdat het bestaat uit 'celebrity'-gezichten die meestal wit zijn. Ten slotte produceert ons DCGAN-model met succes bijna echte beelden van louter ruis.

U kunt ook mijn Github-opslagplaats ook over dit project.

Laten we naar het tweede project gaan: 👇

Ontwikkel en implementeer een gezichtsmaskerdetectiesysteem met OpenCV, Keras en StreamLit

Abstract: In de COVID-19-crisis hebben we gezien dat het dragen van maskers absoluut noodzakelijk is voor de volksgezondheid en het beheersen van de verspreiding van de pandemie. Wat als we als Machine Learning Student een systeem zouden maken dat zou kunnen monitoren of mensen om ons heen zich aan deze veiligheidsmaatregelen houden of niet? Dus in dit project zullen we proberen een gezichtsmaskerdetectorsysteem te maken dat detecteert of een persoon een masker draagt ​​of niet en we zullen dat model ook inzetten in de vorm van een webapp zodat we dat ook in productie kunnen gebruiken .

Gezichtsmaskerdetectiesysteem met AI | Computer Vision-projecten

                                                            Afbeelding 2 

Modelarchitectuur en training

In dit project heb ik gebruik gemaakt van Transfer leren, welke is een zeer eenvoudige taak. Hier gebruikte ik de MobielNetV2 model om mijn classificatienetwerk te bouwen.

Door Transfer Learning te gebruiken, maak ik gebruik van de functiedetectiemogelijkheden van de vooraf getrainde MobileNetV2 en pas ik deze toe op ons vrij eenvoudige model. De MobileNetV2 wordt gevolgd door onze DNN bestaat uit lagen zoals: GlobalAveragePooling, Dicht, en Afvaller. Omdat de onze een binair classificatieprobleem is, heeft de laatste laag 2 neuronen en softmax-activering.

Ik volg ook het algemene idee van het gebruik van Adam-optimizer met Categorische_crossentropie loss to werkt goed omdat deze combinatie van optimizer en loss-functie samenkomt op de meest optimale gewichten voor mijn netwerk.

Importeer de benodigde pakketten

van tensorflow.keras.preprocessing.image import ImageDataGenerator van tensorflow.keras.applications import MobileNetV2 van tensorflow.keras.layers import AveragePooling2D van tensorflow.keras.layers import Dropout van tensorflow.keras.layers import Flatten from tensorflow.kerense.layers van tensorflow.keras.layers import Invoer van tensorflow.keras.models import Model van tensorflow.keras.optimizers import Adam van tensorflow.keras.applications.mobilenet_v2 import preprocess_input van tensorflow.keras.preprocessing.image import img_to_array van tensorflow.keras. .image import load_img van tensorflow.keras.utils import to_categorical van sklearn.preprocessing import LabelBinarizer van sklearn.model_selection import train_test_split van sklearn.metrics import classificatierapport van imutils import paden import matplotlib.pyplot als plt import numpy as plt import numpy as .

De argument-parser gevormd en de argumenten ontleden

ap = argparse.ArgumentParser() ap.add_argument("-d", "--dataset", required=True, help="pad naar invoergegevensset") ap.add_argument("-p", "--plot", type=str, default="plot.png", help="pad naar output loss/nauwkeurigheid plot") ap.add_argument("-m", "--model", type=str, default="mask_detector.model" , help = "pad naar uitvoer gezichtsmaskerdetectormodel") args = vars(ap.parse_args())

De waarden van leersnelheid, aantal tijdperken en batchgrootte geïnitialiseerd

INIT_LR = 1e-4 EPOCHS = 20 BS = 32

Zoek de lijst met afbeeldingen in onze datasetdirectory om de lijst met gegevens en klassenafbeeldingen te initialiseren

print("[INFO] afbeeldingen laden...") imagePaths = list(paths.list_images(args["dataset"])) data = [] labels = []

Loop over de afbeeldingspaden

voor imagePath in imagePaths: # Haal het klasselabel op uit de bestandsnaam label = imagePath.split(os.path.sep)[-2] # laad de invoerafbeelding van dimensie 224x224 en verwerk deze vooraf image = load_img(imagePath, target_size=(224 , 224)) image = img_to_array(image) image = preprocess_input(image) # update gebeurt voor de lijst met gegevens en labels data.append(image) labels.append(label)

Conversie van gegevens en labels naar NumPy-arrays-indeling

data = np.array(data, dtype="float32") labels = np.array(labels)

Voer one-hot-codering uit op de labels

lb = LabelBinarizer() labels = lb.fit_transform(labels) labels = to_categorical(labels)

Verdeel de gegevens in trainings- en testsplitsingen met 75% van de gegevens voor training en de resterende 25% voor testen

(trainX, testX, trainY, testY) = train_test_split(data, labels, test_size=0.20, stratify=labels, random_state=42)

Vormde de trainingsbeeldgenerator ten behoeve van Data Augmentation

aug = ImageDataGenerator (rotation_range=20, zoom_range=0.15, width_shift_range=0.2, height_shift_range=0.2, shear_range=0.15, horizontal_flip=True, fill_mode="nearest")

Laad het MobileNetV2-netwerk en zorg ervoor dat de volledig verbonden lagensets van de kop zijn uitgeschakeld

baseModel = MobileNetV2(weights="imagenet", include_top=False, input_tensor=Input(shape=(224, 224, 3)))

Maak het hoofd van het model voor bovenop het basismodel

headModel = baseModel.output headModel = AveragePooling2D(pool_size=(7, 7))(headModel) headModel = Flatten(name="flatten")(headModel) headModel = Dense(128, activatie="relu")(headModel) headModel = Dropout (0.5) (headModel) headModel = Dicht (2, activatie = "softmax") (headModel)

Plaats het Head Fully Connected-model bovenop het basismodel (word een echt model dat we zullen trainen)

model = Model (inputs=baseModel.input, outputs=headModel)

Doorloop alle lagen in het basismodel en bevries ze zodat ze niet worden bijgewerkt tijdens het eerste trainingsproces

voor laag in baseModel.layers: layer.trainable = False

Modelcompilatie

print("[INFO] compileermodel...") opt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS) model.compile(loss="binary_crossentropy", optimizer=opt, metrics=["nauwkeurigheid"])

Het hoofd van het netwerk trainen

print("[INFO] trainingskop...") H = model.fit( aug.flow(trainX, trainY, batch_size=BS), steps_per_epoch=len(trainX) // BS, validation_data=(testX, testY), validation_steps=len(testX) // BS, tijdperken=EPOCHS)

Voorspellingen doen op de testset

print("[INFO] netwerk evalueren...") predIdxs = model.predict(testX, batch_size=BS)

Probeer voor elke afbeelding in de testset de index van het label te vinden met de bijbehorende grootste voorspelde waarde van de waarschijnlijkheid

predIdxs = np.argmax(predIdxs, as=1)

Het classificatierapport afdrukken

print(classification_report(testY.argmax(axis=1), predIdxs, target_names=lb.classes_))

Output:

Alt-tekst

Serialiseer het model naar schijf

print("[INFO] maskerdetectormodel opslaan...") model.save(args["model"], save_format="h5")

Plot het trainingsverlies en de nauwkeurigheid

N = EPOCHS plt.style.use("ggplot") plt.figure() plt.plot(np.arange(0, N), H.history["loss"], label="train_loss") plt.plot( np.arange(0, N), H.history["val_loss"], label="val_loss") plt.plot(np.arange(0, N), H.history["nauwkeurigheid"], label="train_acc ") plt.plot(np.arange(0, N), H.history["val_accuracy"], label="val_acc") plt.title("Trainingsverlies en nauwkeurigheid") plt.xlabel("Epoch #") plt.ylabel("Verlies/nauwkeurigheid") plt.legend(loc="linksonder") plt.savefig(args["plot"])

Output:

plot.png | Computer Vision-projecten

Uitvoer voor een testafbeelding

In dit gedeelte zal ik beschrijven welk type uitvoer u krijgt nadat u een afbeelding hebt doorgegeven als invoer voor ons gezichtsmaskerdetectiesysteem.

uitgang

Conclusie

Hoera, we hebben met succes 🥳 ons gezichtsmaskerdetectorsysteem gebouwd met een nauwkeurigheid van ongeveer 99%. Voor dit model heb ik ook een webapplicatie gemaakt. Je kunt die code rechtstreeks vanuit mijn GitHub zien en proberen de app ook van jouw kant te maken en in de productieomgeving te gebruiken.

U kunt ook mijn Github-opslagplaats ook over dit project.

Laten we naar het derde en laatste project gaan: 👇

 Beeldruis verwijderen met behulp van AutoEncoders (Encoder-Decoder-netwerk) en U-Net-architectuur met Keras

De algemene autoencoder-architectuur wordt hieronder weergegeven:

Automatische encoders voor computervisie | Computer Vision-projecten

Figuur met de architectuur van een auto-encoder model

                                             Afbeelding 3

Voordat je direct naar het codegedeelte gaat, raad ik je aan eerst dit door te nemen zelfstudie over autoencoders en ga dan door met dit project voor een beter begrip van zowel theoretische als praktische kennis.

Noodzakelijke afhankelijkheden of bibliotheken importeren

Ten eerste moeten we alle benodigde python-bibliotheken of -modules importeren die we in deze implementatie gaan gebruiken.

import numpy als np # Optimalisatie van matrixbewerkingen import matplotlib.pyplot als plt # Datavisualisatie van tensorflow.keras.layers import Conv2D, Input, Dense, Reshape, Conv2DTranspose, Activation, BatchNormalization, ReLU, Concatenate, add, LeakyReLU van tensorflow.keras. modellen importeren Model # Functioneel keras-model van tensorflow.keras.callbacks import ModelCheckpoint # Om de modelgewichten op te slaan op basis van de validatiefout van tensorflow.keras.datasets import cifar100, cifar10 # Vereiste datasets Gebruikt in deze probleemstelling van keras.optimizers import Adam # Optimizer ADAM voor geoptimaliseerde verliesfunctie

Laad de CIFAR-100-gegevensset rechtstreeks vanuit Keras

Om dit te implementeren, gebruiken we de beroemde CIFAR-100 dataset als invoer. Hiervoor hoeven we de dataset niet te downloaden, omdat we deze rechtstreeks uit de Keras-bibliotheek kunnen importeren.

# Gebruikte de CIFAR-100 dataset (train_data_clean, _), (test_data_clean, _) = cifar100.load_data(label_mode='fine')

Normaliseer onze gegevens tussen 0 en 1

Nu verkleinen we onze gegevens in het bereik van [0,1] om de berekeningen te verminderen.

# Om onze gegevens te normaliseren, delen we alle beeldpixels door float(255) train_data_clean = train_data_clean.astype('float32') / 255. test_data_clean = test_data_clean.astype('float32') / 255.

Voeg de ruis toe aan de invoerafbeeldingen

Nu moeten we ruis toevoegen om de afbeeldingen met ruis te genereren. Om ruis toe te voegen, kunnen we een array genereren met dezelfde dimensie van onze afbeeldingen met willekeurige waarden tussen [0,1] met behulp van een normale verdeling met gemiddelde = 0 en standaarddeviatie = 1.

Om de normale verdeling te genereren, kunnen we gebruiken np.willekeurig.normaal(loc,schaal,grootte). Schaal vervolgens de ruis met een bepaalde factor, hier gebruik ik: 0.5. Na het toevoegen van ruis kunnen pixelwaarden buiten bereik zijn, dus we moeten de waarden knippen met np.clip(arr, arr_min, arr_max).

# Functie om de ruis in onze afbeeldingen toe te voegen en de pixelwaarden tussen 0 en 1 te knippen def add_noise_and_clip_data(data, noise_factor): noise = np.random.normal(loc=0.0, scale=0.1, size=data.shape) data = data + noise_factor * noise data = np.clip(data, 0., 1.) return data train_data_noisy = add_noise_and_clip_data(train_data_clean, 0.5) test_data_noisy = add_noise_and_clip_data(test_data_clean, 0.5)

Visualiseer enkele trainingsbeelden met hun luidruchtige beelden

Laten we eens kijken hoe onze trainingsgegevens eruit zien, samen met de bijbehorende afbeeldingen met ruis

rijen = 2 # definiërend nr. aantal rijen in figuur cols = 8 # definiërend nr. van kolommen in figuur f = plt.figure(figsize=(2*cols,2*rows*2)) # definiëren van een figuur voor i in range(rijen): for j in range(cols): f.add_subplot(rijen* 2,cols, (2*i*cols)+(j+1)) # subplot toevoegen aan figuur op elke iteratie plt.imshow(train_data_noisy[i*cols + j]) plt.axis("off") voor j in range(cols): f.add_subplot(rows*2,cols,((2*i+1)*cols)+(j+1)) # subplot toevoegen aan figuur op elke iteratie plt.imshow(train_data_clean[i*cols + j]) plt.axis("uit") f.suptitle("Voorbeeld trainingsgegevens",fontsize=20) plt.show()

Output:

voorbeeld trainingsgegevens | Computer Vision-projecten

Definieer een eenvoudige CNN-architectuur

Hier definiëren we twee functies, namelijk één voor convolutiebewerkingen en de andere voor deconvolutiebewerking om de encoder- en decoderblokken op te nemen in ons aangepaste autoencodermodel.

# Functie om de convolutielagen in onze modelarchitectuur op te nemen def conv_block(x, filters, kernel_size, strides=2): x = Conv2D(filters=filters, kernel_size=kernel_size, strides=strides, padding='same')(x) x = BatchNormalization()(x) x = ReLU()(x) return x # Functie om de deconvolutielagen in onze modelarchitectuur op te nemen def deconv_block(x, filters, kernel_size): x = Conv2DTranspose(filters=filters, kernel_size =kernel_size, strides=2, padding='hetzelfde')(x) x = BatchNormalization()(x) x = ReLU()(x) return x

Functie om de afbeeldingen ongedaan te maken, wordt aan het model gegeven

Nu definiëren we onze hoofdfunctie, die de kern is van onze probleemstelling, aangezien deze functie onze afbeeldingen die we als invoer geven, ongedaan heeft gemaakt en dit is ons hoofddoel van de gegeven probleemstelling.

def denoising_autoencoder(): den_inputs = Input(shape=(32, 32, 3), name='dae_input') conv_block1 = conv_block(den_inputs, 32, 3) conv_block2 = conv_block(conv_block1, 64, 3) conv_block3 = conv_block(conv_block2 , 128, 3) conv_block4 = conv_block(conv_block3, 256, 3) conv_block5 = conv_block(conv_block4, 256, 3, 1) deconv_block1 = deconv_block(conv_block5, 256, 3) merge1 = Concatenate()([deconv_block1, conv_block3]) = deconv_block(merge2, 1, 128) merge3 = Concatenate()([deconv_block2, conv_block2]) deconv_block2 = deconv_block(merge3, 2, 64) merge3 = Concatenate()([deconv_block3, conv_block3]) deconv_block1 = deconv_block(merge4, ​​3 , 32) final_deconv = Conv3DTranspose(filters=2, kernel_size=3, padding='same')(deconv_block3) den_outputs = Activation('sigmoid', name='dae_output')(final_deconv) return Model(den_inputs, den_outputs, name= 'da')

Functiebellen, modelcompilatie en training

In Python moeten we na het maken van een functie deze functie aanroepen door een object van die functie te maken met een aantal gespecificeerde parameters eraan. Daarna compileren en trainen we ons model. Hier kunt u de hyperparameters kiezen, zoals: tijdperken, batch_sizee.d. zelf.

dae = denoising_autoencoder() # Function Calling dae.compile(loss='mse', optimizer='adam') # Model Compilation checkpoint = ModelCheckpoint('best_model.h5', verbose=1, save_best_only=True, save_weights_only=True) # Bewaar de beste gewichten # Training of aanpassing van het model dae.fit(train_data_noisy, train_data_clean, validation_data=(test_data_noisy, test_data_clean), epochs=5, batch_size=128, callbacks=[checkpoint])

Sla de modelgewichten op en voorspel de beelden zonder ruis met behulp van het hierboven getrainde model

Hier laden we de beste gewichten die zijn opgeslagen in het h5-bestand en we gebruiken die gewichten om onze output voor onze testdataset te voorspellen.

dae.load_weights('best_model.h5') # laad de gewichten die we in onze vorige sectie hebben opgeslagen test_data_denoised = dae.predict(test_data_noisy) # Voorspel de uitvoerafbeeldingen met behulp van het getrainde model van de beste gewichten

Druk de originele, luidruchtige en geruisloze versie van een afbeelding af

idx = 4 plt.subplot(1,3,1) plt.imshow(test_data_clean[idx]) plt.title('origineel') plt.subplot(1,3,2) plt.imshow(test_data_noisy[idx]) plt .title('noisy') plt.subplot(1,3,3) plt.imshow(test_data_denoised[idx]) plt.title('denoised') plt.show()

Output:

uitvoer | Computer Vision-projecten

Evalueer het model met MSE

Nu zullen we een functie definiëren om het verschil tussen twee afbeeldingen te berekenen. Hier gebruiken we de gemiddelde kwadratische fout als de verliesfunctie.

def mse(image_1, image_2): return np.square(np.subtract(image_1, image_2)).mean() noise_clean_mse = mse(test_data_clean, test_data_noisy) # MSE tussen initiële en luidruchtige testgegevens denoised_clean_mse = mse(test_data_denoised, test_data_clean) # MSE tussen luidruchtige en opgeschoonde testgegevens gegeven door model noise_clean_mse, denoised_clean_mse # Beide MSE-waarden afdrukken

Onze DAE testen op de CIFAR10-dataset

Nu, na het voltooien van de modeltraining, is het tijd om ons model te testen.

Zoek het verlies tussen de opgeschoonde afbeelding en de invoer waarmee we die afbeelding willen vergelijken

clean_noisy = mse(cifar10_test, cifar10_test_noisy) clean_denoised = mse(cifar10_test, cifar10_test_denoised) clean_noisy, clean_denoised print("Het verschil tussen de twee afbeeldingen is:", clean_noisy-clean_denoised)

Laten we nu een Encoder-Decoder-netwerk ontwerpen met Skip-verbindingen (dwz U-Net-architectuur)

Verbindingen overslaan spelen een zeer belangrijke rol terwijl we werken met elk netwerk waar zowel convoluties als deconvolutiebewerkingen worden uitgevoerd. Het helpt bij het herstellen van de stukjes informatie die verloren kunnen gaan tijdens convolutie en deconvolutie.

Hieronder is de U-Net-architectuur weergegeven:

U-net

Afbeelding met de U-Net architectuur

                                     Image4 

Laten we nu beginnen met het codegedeelte:

size = 32 channel = 3 from keras.layers import Conv2D, Input, Dense, Dropout, MaxPool2D, UpSampling2D # Encoder Component van onze autoencoder-netwerkingangen = Input(shape=(size,size,channel)) x = Conv2D(32, 3 , activatie='relu', padding='same')(inputs) x = BatchNormalization()(x) x = MaxPool2D()(x) x = Dropout(0.5)(x) skip = Conv2D(32, 3, padding ='hetzelfde')(x) # verbinding voor decoder overslaan x = LeakyReLU()(skip) x = BatchNormalization()(x) x = MaxPool2D()(x) x = Dropout(0.5)(x) x = Conv2D( 64, 3, activatie='relu', padding='same')(x) x = BatchNormalization()(x) encoded = MaxPool2D()(x) # Decoder Onderdeel van ons autoencoder-netwerk x = Conv2DTranspose(64, 3, activatie='relu',strides=(2,2), padding='same')(gecodeerd) x = BatchNormalization()(x) x = Dropout(0.5)(x) x = Conv2DTranspose(32, 3, activatie= 'relu',strides=(2,2), padding='same')(x) x = BatchNormalization()(x) x = Dropout(0.5)(x) x = Conv2DTranspose(32, 3, padding='same ')(x) x = add([x,skip]) # toevoegen skip verbinding x = LeakyReLU()(x)x = BatchNormalization()(x) gedecodeerd = Conv2DTranspose(3, 3, activation='sigmoid',strides=(2,2), padding='same')(x) autoencoder = Model(inputs, gedecodeerd) # Compileren van de model autoencoder.compile(optimizer=Adam(learning_rate=0.001), loss='binary_crossentropy') # Analyse van modeloverzicht autoencoder.summary()

Het model trainen of aanpassen

# Fix het aantal tijdperken en batch_size als hyperparameter epochs = 25 batch_size = 256 history = autoencoder.fit(train_data_noisy, train_data_clean, epochs=epochs, batch_size=batch_size, shuffle=True, validation_data=(test_data_noisy, test_data_clean)

De curve van verlies versus aantal tijdperken tekenen

# Definiërende figuur f = plt.figure(figsize=(10,7)) f.add_subplot() # Subplots toevoegen plt.plot(history.epoch, history.history['loss'], label = "loss") # Loss curve voor trainingsset plt.plot(history.epoch, history.history['val_loss'], label = "val_loss") # Verliescurve voor validatieset plt.title("Loss Curve",fontsize=18) plt.xlabel( "Epochs",fontsize=15) plt.ylabel("Loss",fontsize=15) plt.grid(alpha=0.3) plt.legend() plt.savefig("Loss_curve_cifar10.png") plt.show()

Selecteer enkele willekeurige testafbeeldingen

# Aantal te selecteren afbeeldingen num_imgs = 48 rand = np.random.randint(1, test_data_noisy.shape[0]-48) cifar_test_images = test_data_noisy[rand:rand+num_imgs] # slicing cifar_test_denoised = autoencoder.predict) #test_data_clean) voorspellen

Visualiseer testbeelden met hun geruisloze beelden

rijen = 4 # definiërend nr. van rijen in figuur cols = 12 # definiërend nr. van kolommen in figuur cell_size = 1.5 f = plt.figure(figsize=(cell_size*cols,cell_size*rows*2)) # definiëren van een figuur f.tight_layout() for i in range(rows): for j in range(cols ): f.add_subplot(rijen*2,cols, (2*i*cols)+(j+1)) # subplot toevoegen aan figuur op elke iteratie plt.imshow(test_data_clean[i*cols + j]) plt.axis ("off") voor j in range(cols): f.add_subplot(rows*2,cols,((2*i+1)*cols)+(j+1)) # subplot toevoegen aan figuur op elke iteratie plt .imshow(test_data_noisy[i*cols + j]) plt.axis("off") f.suptitle("Autoencoder Results - Cifar10",fontsize=18) plt.show()

Nu zullen we een functie definiëren om het verschil tussen twee afbeeldingen te berekenen. Hier gebruiken we de gemiddelde kwadratische fout als de verliesfunctie

def mse(data_1, data_2): return np.square(np.subtract(data_1, data_2)).mean() noise_clean_mse = mse(test_data_clean, test_data_noisy) denoised_clean_mse = mse(test_data_denoised, test_data_clean) noise_clean_mse_mse_mse_mse

Voorspel de geruisloze versie van een afbeelding

cifar10_test_denoised = autoencoder.predict(cifar10_test_noisy)

Druk de originele, luidruchtige en geruisloze versie van een afbeelding af

idx = 6
plt.subplot(1,3,1)
plt.imshow(cifar10_test[idx])
plt.title('original')
plt.subplot(1,3,2)
plt.imshow(cifar10_test_noisy[idx])
plt.title('noisy')
plt.subplot(1,3,3)
plt.imshow(cifar10_test_denoised[idx])
plt.title('denoised')
plt.show()

Zoek de MSE tussen de afbeeldingen

clean_noisy = mse(cifar10_test, cifar10_test_noisy) clean_denoised = mse(cifar10_test, cifar10_test_denoised) clean_noisy, clean_denoised print("Het verschil tussen de twee afbeeldingen is:", clean_noisy-clean_denoised)

Dat is het voor nu! U kunt uw auto-encoders bouwen 😎😎. Ontdek meer datasets en veel plezier met het trainen van uw eigen auto-encoders.

Conclusie

Autoencoders zijn krachtig en kunnen veel meer. Hier heb ik u kennis laten maken met 2 voorbeelden van eenvoudige modellen, en u kunt zien hoe goed ons model presteerde op de ruisonderdrukkingstaak. Er zijn ook andere toepassingen, zoals het gebruik van een autoencoder voor sequentiële gegevens. Een van zo'n voorbeeld is: Variationele autoencoder (VAE), wat een iets geavanceerder en moderner concept is. Het kan ook worden gebruikt om afbeeldingen te genereren.

U kunt ook mijn Github-opslagplaats ook over dit project.

Hiermee is onze discussie over alle drie de projecten voltooid! 🥳

Speciale dank!

Voor dit artikel wil ik speciale dank betuigen aan Vetrivel_PS die me regelmatig motiveert om dit soort artikelen te schrijven, omdat dit soort artikelen erg nuttig zijn voor alle mensen die ofwel een overstap naar Data Science willen maken of willen uitblinken op het gebied van Data Science.

Als je ook lid wilt worden van Vetrivel's Data Science Community, ga dan naar de Hackweekly Linkedin-community (https://www.linkedin.com/company/thehackweekly) en doe mee.

Over de auteur

Je kunt ook mijn eerdere blogposts bekijken.

Eerdere Data Science-blogberichten.

Hier is mijn Linkedin-profiel voor het geval je met mij in contact wilt komen. Ik ben graag met je verbonden.

E-mail

Voor vragen kunt u mij mailen op Gmail.

Referenties:

Afbeelding 1: https://towardsdatascience.com/fake-face-generator-using-dcgan-model-ae9322ccfd65

Image 2: https://www.google.co.in/url?sa=i&url=https%3A%2F%2Fwww.leewayhertz.com%2Fface-mask-detection-system%2F&psig=AOvVaw02aHbLLICPG-G31GnWPnwF&ust=1629113361404000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCKivvrH2svICFQAAAAAdAAAAABAD

Image 3: https://www.google.co.in/url?sa=i&url=https%3A%2F%2Fwww.analyticsvidhya.com%2Fblog%2F2021%2F01%2Fauto-encoders-for-computer-vision-an-endless-world-of-possibilities%2F&psig=AOvVaw1LmmWrE4OS1_Cjr6QO9pmg&ust=1628144426721000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCODNwvHclvICFQAAAAAdAAAAABAI

Image 4 : https://www.google.co.in/url?sa=i&url=https%3A%2F%2Fwww.researchgate.net%2Ffigure%2FThe-architecture-of-Unet_fig2_334287825&psig=AOvVaw2DB1XzXKEZAAf_mzzSwhlC&ust=1628144257443000&source=images&cd=vfe&ved=0CAsQjRxqFwoTCOi1zaHclvICFQAAAAAdAAAAABAD

Eindnotities

Bedankt voor het lezen!

Ik hoop dat je genoten hebt van het artikel. Als je het leuk vindt, deel het dan ook met je vrienden. Iets niet genoemd of wilt u uw mening delen? Voel je vrij om hieronder commentaar te geven en ik zal contact met je opnemen. 😉

De media die in dit artikel worden getoond, zijn geen eigendom van Analytics Vidhya en worden naar goeddunken van de auteur gebruikt.

PlatoAi. Web3 opnieuw uitgevonden. Gegevensintelligentie versterkt.
Klik hier om toegang te krijgen.

Bron: https://www.analyticsvidhya.com/blog/2021/09/three-computer-vision-projects-to-skyrocket-your-data-science-career/

spot_img

Laatste intelligentie

spot_img

Chat met ons

Hallo daar! Hoe kan ik u helpen?