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.
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.
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.
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. .)
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()
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.
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).
Mise en commun maximale
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()
La figure du bas est le résultat de la mise en commun maximale.
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()
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()
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.
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()
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.
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()
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.
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()
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.
De plus, dans la figure ci-dessous, kernel_size est 5x5 pour la première couche de convolution.
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()
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)
strides=(2,2)
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()
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.
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()
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.
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()
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)
strides=(2,2)
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()
Similaire au rembourrage dans la couche de pliage Le paramètre de remplissage de la couche de pooling spécifie comment remplir.
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()
Recommended Posts