Python: principes de base de la reconnaissance d'image à l'aide de CNN

Reconnaissance d'image par apprentissage profond

Reconnaissance d'image

La reconnaissance d'image est une technologie qui détecte les «choses» et les «caractéristiques» telles que les caractères et les visages qui apparaissent dans les images et les vidéos.

Plus précisément, classification des images, estimation de la position des objets (figure du haut), division de surface des images (figure du bas), etc. Il existe différentes technologies de reconnaissance.

En 2012, une équipe de l'Université de Toronto a annoncé une étude sur la reconnaissance d'images de haute précision à l'aide de l'apprentissage profond. L'intérêt pour l'apprentissage en profondeur a augmenté, et maintenant la reconnaissance des caractères, la reconnaissance faciale, la conduite automatique, les robots domestiques, etc. Il est mis en pratique dans divers domaines.

Dans cet article, il s'appelle CNN (Convolutional Neural Network) J'apprendrai la technologie.

image.png

image.png

CNN

Vue d'ensemble de CNN

Qu'est-ce que CNN (Convolutional Neural Network)?

Il s'agit d'un réseau neuronal qui extrait des caractéristiques à l'aide d'une couche appelée «couche pliante» qui a une structure similaire au champ visuel du cerveau humain.

Par rapport au réseau de neurones couche uniquement entièrement connecté appris dans le cours de base sur l'apprentissage profond Démontre des performances plus élevées dans des domaines tels que la reconnaissance d'image.

La couche convolutive est une couche qui extrait les entités de la même manière que la couche entièrement connectée, mais contrairement à la couche entièrement connectée. Parce qu'il peut traiter des données d'image qui restent bidimensionnelles et extraire des fonctionnalités Il est excellent pour extraire des éléments bidimensionnels tels que des lignes et des coins.

Aussi dans CNN, souvent avec une couche convolutive

Une couche appelée «couche de pooling» est utilisée.

La couche de regroupement réduit les informations obtenues à partir de la couche convolutive Enfin, les images sont classées.

À partir de la session suivante, nous en apprendrons davantage sur chaque couche, construirons un modèle CNN comme le montre la figure 2 et classerons les images.

image.png

image.png

Couche pliante

Comme le montre la figure, la couche de convolution est une couche qui se concentre sur une partie des données d'entrée et examine les caractéristiques de cette image de partie.

Le type de fonctionnalités sur lequel se concentrer est déterminé en définissant correctement les données d'apprentissage et les fonctions de perte. Il sera appris automatiquement.

Par exemple, dans le cas de CNN qui reconnaît les visages, si l'apprentissage se déroule correctement Dans la couche de convolution proche de la couche d'entrée, il s'agit d'une caractéristique des concepts de faible dimension tels que les lignes et les points. Les calques plus proches du calque de sortie se concentreront sur les caractéristiques conceptuelles de plus grande dimension, telles que les yeux et le nez.

(En fait, les concepts d'ordre supérieur tels que les yeux et le nez ne sont pas détectés directement à partir de l'image d'entrée d'origine. Il est détecté sur la base de la combinaison positionnelle de concepts d'ordre inférieur détectés dans la couche proche de la couche d'entrée. )

Une caractéristique remarquable est traitée comme une matrice de poids appelée filtre (noyau) à l'intérieur du programme. Utilisez un filtre pour chaque fonction.

image.png

image.png

image.png

image.png

Dans la figure ci-dessous, pour une image de 9 x 9 x 3 (vertical x horizontal x nombre de canaux (3 canaux de R, V, B)) Cela ressemble à un pliage avec un filtre 3x3x3 (vertical x horizontal x nombre de canaux).

Je crée une nouvelle carte de caractéristiques 4x4x1 (comme une image en noir et blanc) en utilisant un filtre 3x3x3. De plus, nous réaliserons un total de N cartes 4x4x1 en utilisant plusieurs filtres différents. Dans l'ensemble, cette couche de convolution transforme une image 9x9x3 en une carte d'entités 4x4xN.

(En incluant les problèmes suivants dans cette session, un filtre bidimensionnel est souvent utilisé comme exemple pour expliquer la couche de convolution, mais en réalité, un filtre tridimensionnel est souvent utilisé comme le montre la figure ci-dessous. .)

image.png

image.png

Cliquez ici pour un exemple de mise en œuvre simple Implémentons-le sans utiliser Keras + TensorFlow.

import numpy as np
import matplotlib.pyplot as plt
import urllib.request

#Définit une couche de convolution très simple
class Conv:
    #Pour un exemple simple, W est fixé à 3x3, pas de foulées ou de remplissage pour les sessions ultérieures.
    def __init__(self, W):
        self.W = W
    def f_prop(self, X):
        out = np.zeros((X.shape[0]-2, X.shape[1]-2))
        for i in range(out.shape[0]):
            for j in range(out.shape[1]):
                x = X[i:i+3, j:j+3]
                #Je prends la somme des produits pour chaque élément
                out[i,j] = np.dot(self.W.flatten(), x.flatten())
        return out

X = np.load('./5100_cnn_data/circle.npy')

plt.imshow(X)
plt.title("base image", fontsize=12)
plt.show()

#Veuillez configurer le noyau correctement
W1 = np.array([[0,1,0],
               [0,1,0],
               [0,1,0]])

W2 = np.array([[0,0,0],
               [1,1,1],
               [0,0,0]])
W3 = np.array([[1,0,0],
               [0,1,0],
               [0,0,1]])
W4 = np.array([[0,0,1],
               [0,1,0],
               [1,0,0]])

plt.subplot(1,4,1); plt.imshow(W1)
plt.subplot(1,4,2); plt.imshow(W2)
plt.subplot(1,4,3); plt.imshow(W3)
plt.subplot(1,4,4); plt.imshow(W4)
plt.suptitle("kernels", fontsize=12)
plt.show()

#Plier
conv1 = Conv(W1); C1 = conv1.f_prop(X)
conv2 = Conv(W2); C2 = conv2.f_prop(X)
conv3 = Conv(W3); C3 = conv3.f_prop(X)
conv4 = Conv(W4); C4 = conv4.f_prop(X)

plt.subplot(1,4,1); plt.imshow(C1)
plt.subplot(1,4,2); plt.imshow(C2)
plt.subplot(1,4,3); plt.imshow(C3)
plt.subplot(1,4,4); plt.imshow(C4)
plt.suptitle("convolution results", fontsize=12)
plt.show()

image.png

Couche de regroupement

On peut dire que la couche de mise en commun est une couche qui réduit la sortie de la couche de convolution et réduit la quantité de données comme indiqué sur la figure.

Comme le montre la figure

Mise en commun maximale:Prendre la valeur maximale d'une sous-section de la carte des caractéristiques
Mise en commun moyenne:Prenez la moyenne de la carte spéciale
Les données peuvent être compressées en faisant de telles choses.

image.png

Vous pouvez examiner la distribution des caractéristiques dans l'image en effectuant la convolution qui a été traitée dans la session "Pliage de la couche". Les mêmes fonctionnalités sont souvent regroupées et distribuées dans des emplacements similaires De plus, il y a des moments où les endroits où les entités ne peuvent pas être trouvées sont largement distribués. La sortie de la carte d'entités de la couche de convolution est inutile pour la taille de ses données.

La mise en commun peut réduire le gaspillage de ces données et compresser les données tout en réduisant la perte d'informations.

En revanche, les informations de position détaillées seront supprimées par mise en commun. Au contraire, cela signifie que les caractéristiques extraites par la couche de regroupement ne sont pas affectées par le mouvement parallèle de l'image d'origine.

Il joue un rôle de donner de la robustesse.

Par exemple, lors de la classification de nombres manuscrits sur une photo, la position des nombres n'est pas importante, La mise en commun supprime ces informations moins importantes Vous pouvez créer un modèle résistant aux changements de position de l'objet à détecter par rapport à l'image d'entrée.

La figure ci-dessous montre une carte de caractéristiques 5x5 (vertical x horizontal) regroupée tous les 3x3 (vertical x horizontal).

image.png

Mise en commun maximale

image.png

Mise en commun moyenne

Cliquez ici pour une mise en œuvre simple

import numpy as np
import matplotlib.pyplot as plt
import urllib.request

#Il définit une couche convolutive très simple.
class Conv:
    #Pour un exemple simple, W est fixé à 3x3 et nous ne pensons pas aux foulées ou au rembourrage pour les sessions ultérieures.
    def __init__(self, W):
        self.W = W
    def f_prop(self, X):
        out = np.zeros((X.shape[0]-2, X.shape[1]-2))
        for i in range(out.shape[0]):
            for j in range(out.shape[1]):
                x = X[i:i+3, j:j+3]
                out[i,j] = np.dot(self.W.flatten(), x.flatten())
        return out

#Il définit une couche de pooling très simple.
class Pool:
    #Par souci d'exemple simple, nous ne considérerons pas les foulées ou le rembourrage pour les sessions ultérieures.
    def __init__(self, l):
        self.l = l
    def f_prop(self, X):
        l = self.l
        out = np.zeros((X.shape[0]//l, X.shape[1]//l))
        for i in range(out.shape[0]):
            for j in range(out.shape[1]):
                #Faites le pooling Max avec le code ci-dessous.
                out[i,j] = np.max(X[i*l:(i+1)*l, j*l:(j+1)*l])
        return out

X = np.load('./5100_cnn_data/circle.npy')

plt.imshow(X)
plt.title("base image", fontsize=12)
plt.show()

#noyau
W1 = np.array([[0,1,0],
               [0,1,0],
               [0,1,0]])
W2 = np.array([[0,0,0],
               [1,1,1],
               [0,0,0]])
W3 = np.array([[1,0,0],
               [0,1,0],
               [0,0,1]])
W4 = np.array([[0,0,1],
               [0,1,0],
               [1,0,0]])

#Plier
conv1 = Conv(W1); C1 = conv1.f_prop(X)
conv2 = Conv(W2); C2 = conv2.f_prop(X)
conv3 = Conv(W3); C3 = conv3.f_prop(X)
conv4 = Conv(W4); C4 = conv4.f_prop(X)

plt.subplot(1,4,1); plt.imshow(C1)
plt.subplot(1,4,2); plt.imshow(C2)
plt.subplot(1,4,3); plt.imshow(C3)
plt.subplot(1,4,4); plt.imshow(C4)
plt.suptitle("convolution images", fontsize=12)
plt.show()

#mise en commun
pool = Pool(2)
P1 = pool.f_prop(C1)
P2 = pool.f_prop(C2)
P3 = pool.f_prop(C3)
P4 = pool.f_prop(C4)

plt.subplot(1,4,1); plt.imshow(P1)
plt.subplot(1,4,2); plt.imshow(P2)
plt.subplot(1,4,3); plt.imshow(P3)
plt.subplot(1,4,4); plt.imshow(P4)
plt.suptitle("pooling results", fontsize=12)
plt.show()

image.png

La figure du bas est le résultat de la mise en commun maximale.

Mise en œuvre de CNN

Implémentez CNN à l'aide de Keras + TensorFlow.

En pratique, vous utiliserez la plupart du temps ces bibliothèques pour implémenter votre modèle. Dans Keras, créez d'abord une instance qui gère le modèle et utilisez la méthode add pour définir des couches couche par couche.

Créez une instance.

model = Sequential()

Ajoutez des couches du modèle couche par couche en utilisant la méthode d'ajout comme indiqué ci-dessous. La couche entièrement connectée a été définie comme suit.

model.add(Dense(128))

Ajoutez la couche de convolution comme suit. Vous apprendrez les paramètres dans une session ultérieure.

model.add(Conv2D(filters=64, kernel_size=(3, 3)))

Ajoutez la couche de regroupement comme suit. Vous apprendrez les paramètres dans une session ultérieure.

model.add(MaxPooling2D(pool_size=(2, 2)))

Enfin, il compile et termine la génération du modèle de réseau neuronal.

model.compile(optimizer=sgd, loss="categorical_crossentropy", metrics=["accuracy"])

Ce qui suit va générer un tableau avec la structure du modèle en question.

model.summary()

image.png

Cliquez ici pour un exemple simple

from keras.layers import Activation, Conv2D, Dense, Flatten, MaxPooling2D
from keras.models import Sequential, load_model
from keras.utils.np_utils import to_categorical

#Définition du modèle
model = Sequential()

#Exemple d'implémentation
# --------------------------------------------------------------
model.add(Conv2D(input_shape=(28, 28, 1), filters=32, kernel_size=(2, 2), strides=(1, 1), padding="same"))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(1, 1), padding="same"))
model.add(Conv2D(filters=32, kernel_size=(2, 2), strides=(1, 1), padding="same"))
model.add(MaxPooling2D(pool_size=(2, 2), strides=(1,1)))
# --------------------------------------------------------------
model.add(Flatten())
model.add(Dense(256))
model.add(Activation('sigmoid'))
model.add(Dense(128))
model.add(Activation('sigmoid'))
model.add(Dense(10))
model.add(Activation('softmax'))

model.summary()

image.png

Classification à l'aide de CNN (MNIST)

MNIST est un ensemble de données de nombres manuscrits comme indiqué dans la figure ci-dessous. Chaque image a une taille de 28 pixels x 28 pixels et est constituée de données à 1 canal (monochrome). Chacun a une étiquette de classe de 0 à 9.

Nous utiliserons CNN pour classer l'ensemble de données MNIST.

image.png

Cliquez ici pour un exemple de mise en œuvre

from keras.datasets import mnist
from keras.layers import Dense, Dropout, Flatten, Activation
from keras.layers import Conv2D, MaxPooling2D
from keras.models import Sequential, load_model
from keras.utils.np_utils import to_categorical
from keras.utils.vis_utils import plot_model
import numpy as np
import matplotlib.pyplot as plt

#Chargement des données
(X_train, y_train), (X_test, y_test) = mnist.load_data()

#Cette fois, nous utiliserons 300 données pour la formation et 100 données pour les tests.
#La couche Conv reçoit un tableau à 4 dimensions. (Taille du lot x longueur x largeur x nombre de canaux)
#Puisque les données MNIST sont à l'origine des données 3D et non une image RVB, elles sont converties en 4D à l'avance.
X_train = X_train[:300].reshape(-1, 28, 28, 1)
X_test = X_test[:100].reshape(-1, 28, 28, 1)
y_train = to_categorical(y_train)[:300]
y_test = to_categorical(y_test)[:100]

#Définition du modèle
model = Sequential()
model.add(Conv2D(filters=32, kernel_size=(3, 3),input_shape=(28,28,1)))
model.add(Activation('relu'))
model.add(Conv2D(filters=64, kernel_size=(3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(10))
model.add(Activation('softmax'))


model.compile(loss='categorical_crossentropy',
              optimizer='adadelta',
              metrics=['accuracy'])

model.fit(X_train, y_train,
          batch_size=128,
          epochs=1,
          verbose=1,
          validation_data=(X_test, y_test))

#Évaluation de l'exactitude
scores = model.evaluate(X_test, y_test, verbose=1)
print('Test loss:', scores[0])
print('Test accuracy:', scores[1])

#Visualisation des données (10 premières feuilles de données de test)
for i in range(10):
    plt.subplot(2, 5, i+1)
    plt.imshow(X_test[i].reshape((28,28)), 'gray')
plt.suptitle("10 images of test data",fontsize=20)
plt.show()

#Prédiction (10 premières feuilles de données de test)
pred = np.argmax(model.predict(X_test[0:10]), axis=1)
print(pred)

model.summary()

image.png

image.png

Classification à l'aide de CNN (CIFAR-10)

CIFAR-10 (Cipher Ten) est un ensemble de données d'images montrant 10 types d'objets comme le montre l'image ci-dessous.

Chaque image a une taille de 32 pixels x 32 pixels et dispose de 3 canaux (R, V, B) de données. Chacun a une étiquette de classe de 0 à 9. Les objets correspondant à chaque étiquette de classe sont les suivants.

0: avion 1: automobile 2: oiseau 3: chat 4: cerf 5: Chien 6: grenouille 7: Cheval 8: navire 9: camion Nous utiliserons CNN pour classer l'ensemble de données CIFAR-10.

image.png

import keras
from keras.datasets import cifar10
from keras.layers import Activation, Conv2D, Dense, Dropout, Flatten, MaxPooling2D
from keras.models import Sequential, load_model
from keras.utils.np_utils import to_categorical
import numpy as np
import matplotlib.pyplot as plt

#Chargement des données
(X_train, y_train), (X_test, y_test) = cifar10.load_data()

#Cette fois, nous utiliserons 300 de toutes les données pour la formation et 100 pour les tests.
X_train = X_train[:300]
X_test = X_test[:100]
y_train = to_categorical(y_train)[:300]
y_test = to_categorical(y_test)[:100]


#Définition du modèle
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same',
                 input_shape=X_train.shape[1:]))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(10))
model.add(Activation('softmax'))


#compiler
opt = keras.optimizers.rmsprop(lr=0.0001, decay=1e-6)
model.compile(loss='categorical_crossentropy',
              optimizer=opt,
              metrics=['accuracy'])

#Cela prend quelques minutes pour apprendre, alors chargez les poids obtenus par la formation à l'avance.
#model.load_weights('./cnn_data/param_cifar10.hdf5')

#Apprentissage
model.fit(X_train, y_train, batch_size=32, epochs=1)

#Utilisez ce qui suit pour enregistrer les poids. Il ne peut pas être exécuté ici.
# model.save_weights('param_cifar10.hdf5')

#Évaluation de l'exactitude
scores = model.evaluate(X_test, y_test, verbose=1)
print('Test loss:', scores[0])
print('Test accuracy:', scores[1])

#Visualisation des données (10 premières feuilles de données de test)
for i in range(10):
    plt.subplot(2, 5, i+1)
    plt.imshow(X_test[i])
plt.suptitle("10 images of test data",fontsize=20)
plt.show()

#Prédiction (10 premières feuilles de données de test)
pred = np.argmax(model.predict(X_test[0:10]), axis=1)
print(pred)

model.summary()

image.png

image.png

Hyper paramètres

filtres (couche Conv)

Le paramètre des filtres pour la couche convolutive est
Spécifie le nombre de mappes d'entités à générer, c'est-à-dire le type d'entités à extraire.

Dans la figure ci-dessous Les filtres sont 20 dans la première couche de convolution Les filtres seront 20 même dans la deuxième couche de convolution.

image.png

Si les filtres sont trop petits pour extraire les fonctionnalités requises, vous ne pourrez pas bien poursuivre l'apprentissage. En revanche, s'il est trop grand, il sera facile de surapprendre, alors soyez prudent.

Implémentons-le sans utiliser Keras + TensorFlow.

import numpy as np
import matplotlib.pyplot as plt

#Il définit une couche convolutive très simple.
#Seule la convolution d'image à 1 canal est supposée.
#Pour un exemple simple, le noyau est fixé à 3x3, pas de foulées ou de rembourrage.
class Conv:
    def __init__(self, filters):
        self.filters = filters
        self.W = np.random.rand(filters,3,3)
    def f_prop(self, X):
        out = np.zeros((filters, X.shape[0]-2, X.shape[1]-2))
        for k in range(self.filters):
            for i in range(out[0].shape[0]):
                for j in range(out[0].shape[1]):
                    x = X[i:i+3, j:j+3]
                    out[k, i, j] = np.dot(self.W[k].flatten(), x.flatten())
        return out

X = np.load('./5100_cnn_data/circle.npy')

filters=10

#Génération de couche convolutive
conv = Conv(filters=filters)

#Exécution de la convolution
C = conv.f_prop(X)

# --------------------------------------------------------------
#Vous trouverez ci-dessous tout le code de visualisation.
# --------------------------------------------------------------

plt.imshow(X)
plt.title('base image', fontsize=12)
plt.show()

plt.figure(figsize=(5,2))
for i in range(filters):
    plt.subplot(2,filters/2,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(conv.W[i])
plt.suptitle('kernels', fontsize=12)
plt.show()

plt.figure(figsize=(5,2))
for i in range(filters):
    plt.subplot(2,filters/2,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(C[i])
plt.suptitle('convolution results', fontsize=12)
plt.show()

image.png

kernel_size (couche Conv)

Le paramètre kernel_size de la couche de convolution est Spécifie la taille du noyau (la matrice de poids utilisée pour la convolution).

Comme mentionné ci-dessus, la carte des caractéristiques est déterminée par l'ensemble des produits des données d'entrée et du noyau. La figure ci-dessous est un noyau 3x3. Chaque élément reçoit un nombre arbitraire pour une convolution optimale.

image.png

De plus, dans la figure ci-dessous, kernel_size est 5x5 pour la première couche de convolution.

image.png

Si kernel_size est trop petit, même les très petites fonctionnalités ne peuvent pas être détectées et l'apprentissage ne peut pas se dérouler correctement.

Au contraire, s'il est trop grand, il aurait dû être détecté comme un ensemble de petits éléments. Même les grandes fonctionnalités seront détectées

Ne pas profiter de la force du modèle de réseau neuronal, qui est bon pour capturer les structures hiérarchiques Ce sera un modèle inefficace.

Cliquez ici pour un exemple de mise en œuvre

import numpy as np
import matplotlib.pyplot as plt

#Il définit une couche convolutive très simple.
#Seule la convolution d'image à 1 canal est supposée.
#Je ne pense pas aux foulées ou au rembourrage parce que je pense à un exemple simple.
class Conv:
    def __init__(self, filters, kernel_size):
        self.filters = filters
        self.kernel_size = kernel_size
        self.W = np.random.rand(filters, kernel_size[0], kernel_size[1])
    def f_prop(self, X):
        k_h, k_w = self.kernel_size
        out = np.zeros((filters, X.shape[0]-k_h+1, X.shape[1]-k_w+1))
        for k in range(self.filters):
            for i in range(out[0].shape[0]):
                for j in range(out[0].shape[1]):
                    x = X[i:i+k_h, j:j+k_w]
                    out[k,i,j] = np.dot(self.W[k].flatten(), x.flatten())
        return out

X = np.load('./5100_cnn_data/circle.npy')

#Pliage 1
filters = 4
kernel_size = (3,3)

#Génération de couche convolutive
conv1 = Conv(filters=filters, kernel_size=kernel_size)

#Exécution de la convolution
C1 = conv1.f_prop(X)

#Pliage 2
filters = 4
kernel_size = (6,6)

#Génération de couche convolutive
conv2 = Conv(filters=filters, kernel_size=kernel_size)

#Exécution de la convolution
C2 = conv2.f_prop(X)

#Voici tout le code pour la visualisation

plt.imshow(X)
plt.title('base image', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(conv1.W[i])
plt.suptitle('kernel visualization', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(C1[i])
plt.suptitle('convolution results 1', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(conv2.W[i])
plt.suptitle('kernel visualization', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(C2[i])
plt.suptitle('convolution results 2', fontsize=12)
plt.show()

image.png

foulées (couche Conv)

Le paramètre de foulées de la couche convolutionnelle est l'intervalle auquel les entités sont extraites. En d'autres termes, spécifiez la distance pour déplacer le noyau.

strides=(1,1)

image.png

strides=(2,2)

image.png

Plus les foulées sont petites, plus les caractéristiques peuvent être extraites. Par exemple, la même entité au même endroit dans l'image est détectée plusieurs fois. Il semble qu'il y ait beaucoup de calculs inutiles.

Cependant, on dit généralement que les petites foulées sont meilleures. Dans la couche Conv2D de Keras, les foulées sont par défaut (1,1).

import numpy as np
import matplotlib.pyplot as plt

#Il définit une couche convolutive très simple.
#Seule la convolution d'image à 1 canal est supposée.
#Je ne pense pas au rembourrage parce que je pense à un exemple simple.
class Conv:
    def __init__(self, filters, kernel_size, strides):
        self.filters = filters
        self.kernel_size = kernel_size
        self.strides = strides
        self.W = np.random.rand(filters, kernel_size[0], kernel_size[1])
    def f_prop(self, X):
        k_h = self.kernel_size[0]
        k_w = self.kernel_size[1]
        s_h = self.strides[0]
        s_w = self.strides[1]
        out = np.zeros((filters, (X.shape[0]-k_h)//s_h+1, (X.shape[1]-k_w)//s_w+1))
        for k in range(self.filters):
            for i in range(out[0].shape[0]):
                for j in range(out[0].shape[1]):
                    x = X[i*s_h:i*s_h+k_h, j*s_w:j*s_w+k_w]
                    out[k,i,j] = np.dot(self.W[k].flatten(), x.flatten())
        return out

X = np.load('./5100_cnn_data/circle.npy')

#Pliage 1
filters = 4
kernel_size = (3,3)
strides = (1,1)

#Génération de couche convolutive
conv1 = Conv(filters=filters, kernel_size=kernel_size, strides=strides)

#Exécution de la convolution
C1 = conv1.f_prop(X)

#Pliage 2
filters = 4
kernel_size = (3,3)
strides = (2,2)

#Génération de couche convolutive
conv2 = Conv(filters=filters, kernel_size=kernel_size, strides=strides)
conv2.W = conv1.W #Noyau unifié

#Exécution de la convolution
C2 = conv2.f_prop(X)

#Voici tout le code pour la visualisation

plt.imshow(X)
plt.title('base image', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(conv1.W[i])
plt.suptitle('kernel visualization', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(C1[i])
plt.suptitle('convolution results 1', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(conv2.W[i])
plt.suptitle('kernel results', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(C2[i])
plt.suptitle('convolution results 2', fontsize=12)
plt.show()

image.png

rembourrage (couche Conv)

Le remplissage sert à empêcher l'image de rétrécir une fois pliée. Ajout de pixels autour de l'image d'entrée.

Généralement, le pixel à ajouter est défini sur 0. Remplissez la zone autour de cette image d'entrée avec 0 C'est ce qu'on appelle le remplissage nul.

Le remplissage prend également en compte les caractéristiques des données de bord. En outre, la fréquence des mises à jour des données augmentera Il y a des avantages tels que la possibilité d'ajuster le nombre d'unités d'entrée / sortie pour chaque couche.

Le cadre blanc autour du panneau orange dans la figure ci-dessous représente le remplissage. Ceci est une figure avec 1 rembourrage haut et bas et 1 rembourrage gauche et droite. image.png

Dans la couche Conv2D de Keras Spécifiez la méthode de remplissage telle que padding = valid, padding = same.

padding=Si valide, aucun remplissage n'est effectué
padding=Dans le cas contraire, la carte des entités en sortie doit correspondre à la taille de l'entrée
L'entrée est complétée.

Le même code prend la largeur de remplissage comme argument, tel que padding = (1,1).

import numpy as np
import matplotlib.pyplot as plt
import urllib.request

#Il définit une couche convolutive très simple.
#Seule la convolution d'image à 1 canal est supposée.
class Conv:
    def __init__(self, filters, kernel_size, strides, padding):
        self.filters = filters
        self.kernel_size = kernel_size
        self.strides = strides
        self.padding = padding
        self.W = np.random.rand(filters, kernel_size[0], kernel_size[1])
    def f_prop(self, X):
        k_h, k_w = self.kernel_size
        s_h, s_w = self.strides
        p_h, p_w = self.padding
        out = np.zeros((filters, (X.shape[0]+p_h*2-k_h)//s_h+1, (X.shape[1]+p_w*2-k_w)//s_w+1))
        #Rembourrage
        X = np.pad(X, ((p_h, p_h), (p_w, p_w)), 'constant', constant_values=((0,0),(0,0)))
        self.X = X #Enregistrez-le pour une visualisation ultérieure des résultats de remplissage.
        for k in range(self.filters):
            for i in range(out[0].shape[0]):
                for j in range(out[0].shape[1]):
                    x = X[i*s_h:i*s_h+k_h, j*s_w:j*s_w+k_w]
                    out[k,i,j] = np.dot(self.W[k].flatten(), x.flatten())
        return out

X = np.load('./5100_cnn_data/circle.npy')

#Pliage 1
filters = 4
kernel_size = (3,3)
strides = (1,1)
padding = (0,0)

#Génération de couche convolutive
conv1 = Conv(filters=filters, kernel_size=kernel_size, strides=strides, padding=padding)

#Exécution de la convolution
C1 = conv1.f_prop(X)

#Pliage 2
filters = 4
kernel_size = (3,3)
strides = (1,1)
padding = (2,2)

#Génération de couche convolutive
conv2 = Conv(filters=filters, kernel_size=kernel_size, strides=strides, padding=padding)
conv2.W = conv1.W #Le poids est unifié

#Exécution de la convolution
C2 = conv2.f_prop(X)

#Vous trouverez ci-dessous tout le code de visualisation.

plt.imshow(conv1.X)
plt.title('padding results of the convolution 1', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(conv1.W[i])
plt.suptitle('kernel visualization of the convolution 1', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(C1[i])
plt.suptitle('results of the convolution 1', fontsize=12)
plt.show()

plt.imshow(conv2.X)
plt.title('padding results of the convolution 2', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(conv2.W[i])
plt.suptitle('kernel visualization of the convolution 2', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(C2[i])
plt.suptitle('results of the convolution 2', fontsize=12)
plt.show()

image.png

pool_size (couche Pool)

Le paramètre pool_size de la couche de pooling est Paramètre qui spécifie la taille de la zone à laquelle le regroupement est appliqué à un moment donné (rugosité du regroupement).

Dans la figure ci-dessous, la première taille de mise en commun est 2x2 et la deuxième taille de mise en commun est également 2x2.

image.png

En augmentant pool_size Augmentation de la robustesse au positionnement (La sortie ne change pas même si la position où l'objet apparaît dans l'image change légèrement) Fondamentalement, pool_size doit être 2x2.

import numpy as np
import matplotlib.pyplot as plt

#Il définit une couche convolutive très simple.
class Conv:
    def __init__(self, W, filters, kernel_size):
        self.filters = filters
        self.kernel_size = kernel_size
        self.W = W # np.random.rand(filters, kernel_size[0], kernel_size[1])
    def f_prop(self, X):
        k_h, k_w = self.kernel_size
        out = np.zeros((filters, X.shape[0]-k_h+1, X.shape[1]-k_w+1))
        for k in range(self.filters):
            for i in range(out[0].shape[0]):
                for j in range(out[0].shape[1]):
                    x = X[i:i+k_h, j:j+k_w]
                    out[k,i,j] = np.dot(self.W[k].flatten(), x.flatten())
        return out

#Il définit une couche de pooling très simple.
#Seule la mise en commun de la carte d'entités à 1 canal est supposée.
class Pool:
    def __init__(self, pool_size):
        self.pool_size = pool_size
    def f_prop(self, X):
        k_h, k_w = self.pool_size
        out = np.zeros((X.shape[0]-k_h+1, X.shape[1]-k_w+1))
        for i in range(out.shape[0]):
            for j in range(out.shape[1]):
                out[i,j] = np.max(X[i:i+k_h, j:j+k_w])
        return out

X = np.load('./5100_cnn_data/circle.npy')

W = np.load('./5100_cnn_data/weight.npy') 

#Plier
filters = 4
kernel_size = (3,3)
conv = Conv(W=W, filters=filters, kernel_size=kernel_size)
C = conv.f_prop(X)

#Mise en commun 1
pool_size = (2,2)
pool1 = Pool(pool_size)
P1 = [pool1.f_prop(C[i]) for i in range(len(C))]

#Regroupement 2
pool_size = (4,4)
pool2 = Pool(pool_size)
P2 = [pool2.f_prop(C[i]) for i in range(len(C))]

#Vous trouverez ci-dessous tout le code de visualisation.

plt.imshow(X)
plt.title('base image', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(C[i])
plt.suptitle('convolution results', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(P1[i])
plt.suptitle('pooling results', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(P2[i])
plt.suptitle('pooling results', fontsize=12)
plt.show()

image.png

foulées (couche Pool)

Le paramètre stripes de la couche de pooling est Similaire au paramètre de foulées de la couche de convolution, il spécifie l'intervalle auquel la carte d'entités est regroupée.

strides=(1,1)

image.png

strides=(2,2)

image.png

Dans la couche Pooling de Keras, les foulées Par défaut, il correspond à pool_size.

import numpy as np
import matplotlib.pyplot as plt

#Il définit une couche convolutive très simple.
class Conv:
    def __init__(self, W, filters, kernel_size):
        self.filters = filters
        self.kernel_size = kernel_size
        self.W = W # np.random.rand(filters, kernel_size[0], kernel_size[1])
    def f_prop(self, X):
        k_h, k_w = self.kernel_size
        out = np.zeros((filters, X.shape[0]-k_h+1, X.shape[1]-k_w+1))
        for k in range(self.filters):
            for i in range(out[0].shape[0]):
                for j in range(out[0].shape[1]):
                    x = X[i:i+k_h, j:j+k_w]
                    out[k,i,j] = np.dot(self.W[k].flatten(), x.flatten())
        return out

#Il définit une couche de pooling très simple.
#Seule la mise en commun de la carte d'entités à 1 canal est supposée.
class Pool:
    def __init__(self, pool_size, strides):
        self.pool_size = pool_size
        self.strides = strides
    def f_prop(self, X):
        k_h, k_w = self.pool_size
        s_h, s_w = self.strides
        out = np.zeros(((X.shape[0]-k_h)//s_h+1, (X.shape[1]-k_w)//s_w+1))
        for i in range(out.shape[0]):
            for j in range(out.shape[1]):
                out[i,j] = np.max(X[i*s_h:i*s_h+k_h, j*s_w:j*s_w+k_w])
        return out

X = np.load('./5100_cnn_data/circle.npy')

W = np.load('./5100_cnn_data/weight.npy')

#Plier
filters = 4
kernel_size = (3,3)
conv = Conv(W=W, filters=filters, kernel_size=kernel_size)
C = conv.f_prop(X)

#Mise en commun 1
pool_size = (2,2)
strides = (1,1)
pool1 = Pool(pool_size, strides)
P1 = [pool1.f_prop(C[i]) for i in range(len(C))]

#Regroupement 2
pool_size = (3,3)
strides = (2,2)
pool2 = Pool((3,3), (2,2))
P2 = [pool2.f_prop(C[i]) for i in range(len(C))]

# --------------------------------------------------------------
#Vous trouverez ci-dessous tout le code de visualisation.
# --------------------------------------------------------------

plt.imshow(X)
plt.title('base image', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(C[i])
plt.suptitle('convolution results', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(P1[i])
plt.suptitle('pooling results', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(P2[i])
plt.suptitle('pooling results', fontsize=12)
plt.show()

image.png

rembourrage (couche de piscine)

Similaire au rembourrage dans la couche de pliage Le paramètre de remplissage de la couche de pooling spécifie comment remplir.

image.png

Dans la couche MaxPooling2D de Keras Spécifiez la méthode de remplissage telle que padding = valid, padding = same.

padding=Si valide, aucun remplissage n'est effectué
padding=Dans le cas contraire, la carte des entités en sortie doit correspondre à la taille de l'entrée
L'entrée est complétée.

Le code de droite prend la largeur de remplissage comme argument, tel que padding = (1,1).

import numpy as np
import matplotlib.pyplot as plt

#Il définit une couche convolutive très simple.
class Conv:
    def __init__(self, W, filters, kernel_size):
        self.filters = filters
        self.kernel_size = kernel_size
        self.W = W # np.random.rand(filters, kernel_size[0], kernel_size[1])
    def f_prop(self, X):
        k_h, k_w = self.kernel_size
        out = np.zeros((filters, X.shape[0]-k_h+1, X.shape[1]-k_w+1))
        for k in range(self.filters):
            for i in range(out[0].shape[0]):
                for j in range(out[0].shape[1]):
                    x = X[i:i+k_h, j:j+k_w]
                    out[k,i,j] = np.dot(self.W[k].flatten(), x.flatten())
        return out

#Il définit une couche de pooling très simple.
#Seule la mise en commun de la carte d'entités à 1 canal est supposée.
class Pool:
    def __init__(self, pool_size, strides, padding):
        self.pool_size = pool_size
        self.strides = strides
        self.padding = padding
    def f_prop(self, X):
        k_h, k_w = self.pool_size
        s_h, s_w = self.strides
        p_h, p_w = self.padding
        out = np.zeros(((X.shape[0]+p_h*2-k_h)//s_h+1, (X.shape[1]+p_w*2-k_w)//s_w+1))
        X = np.pad(X, ((p_h,p_h),(p_w,p_w)), 'constant', constant_values=((0,0),(0,0)))
        for i in range(out.shape[0]):
            for j in range(out.shape[1]):
                out[i,j] = np.max(X[i*s_h:i*s_h+k_h, j*s_w:j*s_w+k_w])
        return out

X = np.load('./5100_cnn_data/circle.npy')

W = np.load('./5100_cnn_data/weight.npy')

#Plier
filters = 4
kernel_size = (3,3)
conv = Conv(W=W, filters=filters, kernel_size=kernel_size)
C = conv.f_prop(X)

#mise en commun
pool_size = (2,2)
strides = (2,2)
padding = (0,0)
pool1 = Pool(pool_size=pool_size, strides=strides, padding=padding)
P1 = [pool1.f_prop(C[i]) for i in range(len(C))]

#mise en commun
pool_size = (2,2)
strides = (2,2)
padding = (1,1)
pool2 = Pool(pool_size=pool_size, strides=strides, padding=padding)
P2 = [pool2.f_prop(C[i]) for i in range(len(C))]

# --------------------------------------------------------------
#Vous trouverez ci-dessous tout le code de visualisation.
# --------------------------------------------------------------

plt.imshow(X)
plt.title('base image', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(C[i])
plt.suptitle('convolution results', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(P1[i])
plt.suptitle('pooling results', fontsize=12)
plt.show()

plt.figure(figsize=(10,1))
for i in range(filters):
    plt.subplot(1,filters,i+1)
    ax = plt.gca() # get current axis
    ax.tick_params(labelbottom="off", labelleft="off", bottom="off", left="off") #Supprimer l'axe
    plt.imshow(P2[i])
plt.suptitle('pooling results', fontsize=12)
plt.show()

image.png

Recommended Posts

Python: principes de base de la reconnaissance d'image à l'aide de CNN
Python: Application de la reconnaissance d'image à l'aide de CNN
Principes de base de la reconnaissance d'image CNN 1
python: principes de base de l'utilisation de scikit-learn ①
Application de la reconnaissance d'image CNN2
Capture d'image de Firefox en utilisant Python
Reconnaissance d'image des fruits avec VGG16
Les bases de Python ①
Bases de python ①
Bases du traitement d'images binarisées par Python
Reconnaissance d'image à l'aide de chevaux et de cerfs CNN
Principes de base du grattage Python
# 4 [python] Bases des fonctions
Bases de python: sortie
Reconnaissance d'accords à l'aide du chromagramme de la bibliothèque de python librosa
Traitement d'image par matrice Basics & Contents-Reinventor of Python image processing-
Bases de l'écran d'entrée / sortie en utilisant tkinter en python3
Principes de base de Python x SIG (1)
J'ai essayé la reconnaissance de caractères manuscrits des caractères runiques avec CNN en utilisant Keras
Principes de base de Python x SIG (3)
Paiza Python Primer 5: Principes de base des dictionnaires
[Python] Utilisation d'OpenCV avec Python (filtrage d'image)
Jugement de l'image rétroéclairée avec OpenCV
[Python] Utilisation d'OpenCV avec Python (transformation d'image)
Suppression de la brume à l'aide de Python detailEnhanceFilter
Premiers pas avec Python Bases de Python
python x tensoflow x reconnaissance de visage d'image
Revue des bases de Python (FizzBuzz)
Principes de base de Python x SIG (partie 2)
Implémentation des notifications de bureau à l'aide de Python
Implémentation de Light CNN (Python Keras)
Construction et bases de l'environnement de reconnaissance d'image
Reconnaissance de caractères manuscrits à l'aide de KNN en Python
À propos de la liste de base des bases de Python
Apprenez les bases de Python ① Débutants élémentaires
Les bases de Python ⑤
Les bases de Python
Essai de la reconnaissance vocale à l'aide d'Azure avec Python (entrée depuis le microphone)
Les bases de Python ④
Les bases de Python ③
Les bases de Python
Les bases de Python
Reconnaissance d'image
Les bases de Python
Les bases de Python ③
Les bases de Python ②
Les bases de Python ②
Collecte automatique des cours boursiers à l'aide de python
À propos de la création de l'interface graphique à l'aide de TKinter de Python
Estimation de catégorie à l'aide de l'API de reconnaissance d'image de docomo
Pratique d'utilisation de ceci en Python (mauvais)
[Mémo d'apprentissage] Bases de la classe par python
[Python3] Comprendre les bases de Beautiful Soup
Modèle de reconnaissance d'image utilisant l'apprentissage profond en 2016
Introduction facile de la reconnaissance vocale avec Python
[Python] Calcul de la similarité d'image (coefficient de dés)
Je ne connaissais pas les bases de Python
Échelle de gris par matrice-Reinventor of Python image processing-
Principes de base pour exécuter NoxPlayer en Python