Explorar el Código

Merge remote-tracking branch 'origin/Emilien'

Emile2
Emile Siboulet hace 4 años
padre
commit
afddae8f17
Se han modificado 4 ficheros con 192 adiciones y 19 borrados
  1. 17
    1
      README.md
  2. 7
    8
      code/resnet18/resnet18.py
  3. 17
    10
      code/resnet18/resnet18_snake.py
  4. 151
    0
      code/resnet18/resnet_snake.ipynb

+ 17
- 1
README.md Ver fichero

@@ -21,4 +21,20 @@
└── rapport.tex # Fichier source du rapport
```

## To do list
## Emilien

Cette partie s'intéresse à l'efficacité de la fonction d'activation snake sur une tâche complexe de machine learning non-périodique. En effet pour que snake soit intéressant il faut qu'elle fasse aussi bien dans la plupart des tâches de ML comme la classification.
C'est pourquoi conformément à l'article un réseau de CNN ResNet18 est appliqué sur la base de données ciphar-10.

Pour utiliser :

Aller dans code/resnet18/

---> le fichier ResNet18.py est le script POO implémentant le réseau, les classes crées sont :

-- ResnetBlock une superclasse dont hérite la classe ResNet18, créant les resblock faisant apportant l'info résiduelle via la fonction call
-- ResNet18 qui implémente la structure de couches de convolution, elle prend comme argument le nombre de classe possible. Soit 10 dans le cas de CIPHAR-10
Pour faire varier la fonction d'activation --> juste décommenter #tf.nn.relu(x) lignes 44, 54, 84 et commenter x + tf.sin(x)**2

--> le fichier resnet_snake.ipynb est le notebook main python a exectuer faisant l'appel de toutes les fonctions ainsi que de la classe Resnet18

+ 7
- 8
code/resnet18/resnet18.py Ver fichero

@@ -20,7 +20,6 @@ class ResnetBlock(Model):
self.__strides = [2, 1] if down_sample else [1, 1]

KERNEL_SIZE = (3, 3)
# use He initialization, instead of Xavier (a.k.a 'glorot_uniform' in Keras), as suggested in [2]
INIT_SCHEME = "he_normal"

self.conv_1 = Conv2D(self.__channels, strides=self.__strides[0],
@@ -32,8 +31,8 @@ class ResnetBlock(Model):
self.merge = Add()

if self.__down_sample:
# perform down sampling using stride of 2, according to [1].
self.res_conv = Conv2D(
self.res_conv = Conv2D(
self.__channels, strides=2, kernel_size=(1, 1), kernel_initializer=INIT_SCHEME, padding="same")
self.res_bn = BatchNormalization()

@@ -42,7 +41,7 @@ class ResnetBlock(Model):

x = self.conv_1(inputs)
x = self.bn_1(x)
x = tf.nn.relu(x)
x = x + tf.sin(x)**2 #tf.nn.relu(x)
x = self.conv_2(x)
x = self.bn_2(x)

@@ -50,9 +49,9 @@ class ResnetBlock(Model):
res = self.res_conv(res)
res = self.res_bn(res)

# if not perform down sample, then add a shortcut directly
x = self.merge([x, res])
out = tf.nn.relu(x)
out = x + tf.sin(x)**2 #tf.nn.relu(x)
return out


@@ -77,12 +76,12 @@ class ResNet18(Model):
self.res_4_2 = ResnetBlock(512)
self.avg_pool = GlobalAveragePooling2D()
self.flat = Flatten()
self.fc = Dense(num_classes, activation="softmax")
self.fc = Dense(num_classes, activation="sigmoid")

def call(self, inputs):
out = self.conv_1(inputs)
out = self.init_bn(out)
out = tf.nn.relu(out)
out += tf.sin(out)**2 #tf.nn.relu(out)
out = self.pool_2(out)
for res_block in [self.res_1_1, self.res_1_2, self.res_2_1, self.res_2_2, self.res_3_1, self.res_3_2, self.res_4_1, self.res_4_2]:
out = res_block(out)

+ 17
- 10
code/resnet18/resnet18_snake.py Ver fichero

@@ -1,14 +1,12 @@
# Réseau inspiré de http://yann.lecun.com/exdb/publis/pdf/lecun-98.pdf


from keras.callbacks import History

from tensorflow.python.ops.gen_array_ops import tensor_scatter_min_eager_fallback
from resnet18 import ResNet18
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
# Pour les utilisateurs de MacOS (pour utiliser plt & keras en même temps)
import os
#os.environ['KMP_DUPLICATE_LIB_OK']='True'


def displayConvFilers(model, layer_name, num_filter=4, filter_size=(3,3), num_channel=0, fig_size=(2,2)):
@@ -35,21 +33,30 @@ def snake(x):
## Chargement et normalisation des données
resnet18 = tf.keras.datasets.cifar10
(train_images, train_labels), (test_images, test_labels) = resnet18.load_data()
train_images = train_images.astype('float32')
test_images = test_images.astype('float32')

from sklearn.model_selection import train_test_split
train_images, val_images, train_labels, val_labels = train_test_split(train_images,train_labels, test_size = 0.2,shuffle = True)



'''
val_images = train_images[40000:]
val_labels = train_labels[40000:]

train_images = train_images[:40000]
train_labels = train_labels[:40000]
'''

train_images = train_images / 255.0
val_images = val_images /255.0
test_images = test_images / 255.0

# POUR LES CNN : On rajoute une dimension pour spécifier qu'il s'agit d'imgages en NdG
train_images = train_images.reshape(40000,32,32,3)
val_images = val_images.reshape(10000,32,32,3)
test_images = test_images.reshape(10000,32,32,3)
train_images = train_images.reshape(max(np.shape(train_images)),32,32,3)
val_images = val_images.reshape(max(np.shape(val_images)),32,32,3)
test_images = test_images.reshape(max(np.shape(test_images)),32,32,3)


# One hot encoding
@@ -61,9 +68,9 @@ filter_size_conv1 = (3,3)

model = ResNet18(10)
model.build(input_shape = (None,32,32,3))
filter_size_conv1 = (5,5)

'''
filter_size_conv1 = (5,5)
## Définition de l'architecture du modèle
model = tf.keras.models.Sequential()
# Expliquez à quoi correspondent les valeurs numériques qui définissent les couches du réseau
@@ -92,8 +99,8 @@ model.compile(sgd, loss='categorical_crossentropy', metrics=['accuracy'])

history = model.fit(train_images,
train_labels,
batch_size=64,
epochs=4,
batch_size=256,
epochs=50,
validation_data=(val_images, val_labels),
)


+ 151
- 0
code/resnet18/resnet_snake.ipynb Ver fichero

@@ -0,0 +1,151 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "Untitled1.ipynb",
"provenance": [],
"collapsed_sections": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "hUYO09lse0Ew"
},
"outputs": [],
"source": [
"from tensorflow.python.ops.gen_array_ops import tensor_scatter_min_eager_fallback\n",
"from resnet18 import ResNet18\n",
"import tensorflow as tf\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"\n",
"def snake(x):\n",
" return x + tf.sin(x)**2\n",
"\n"
]
},
{
"cell_type": "code",
"source": [
"## Chargement et normalisation des données\n",
"resnet18 = tf.keras.datasets.cifar10\n",
"(train_images, train_labels), (test_images, test_labels) = resnet18.load_data()\n",
"train_images = train_images.astype('float32')\n",
"test_images = test_images.astype('float32')\n",
"\n",
"from sklearn.model_selection import train_test_split\n",
"train_images, val_images, train_labels, val_labels = train_test_split(train_images,train_labels, test_size = 0.2,shuffle = True)\n",
"\n",
"train_images = train_images / 255.0\n",
"val_images = val_images /255.0\n",
"test_images = test_images / 255.0\n",
"\n",
"# POUR LES CNN : un tenseur d'ordre 3 pour les images en couleurs\n",
"train_images = train_images.reshape(max(np.shape(train_images)),32,32,3)\n",
"val_images = val_images.reshape(max(np.shape(val_images)),32,32,3)\n",
"test_images = test_images.reshape(max(np.shape(test_images)),32,32,3)\n",
"\n",
"\n"
],
"metadata": {
"id": "-iczeI91fEND"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# One hot encoding\n",
"train_labels = tf.keras.utils.to_categorical(train_labels)\n",
"val_labels = tf.keras.utils.to_categorical(val_labels)\n",
"test_labels = tf.keras.utils.to_categorical(test_labels)\n",
"\n",
"filter_size_conv1 = (3,3)\n",
"\n",
"\n",
"#création du réseau ResNet18\n",
"\n",
"model = ResNet18(10)\n",
"model.build(input_shape = (None,32,32,3))\n",
"print(model.summary())\n"
],
"metadata": {
"id": "9UGNJFoRfGTz"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"#Adam comme optimizer et categorical-crossentropy comme norme\n",
"sgd = tf.keras.optimizers.Adam()\n",
"model.compile(sgd, loss='categorical_crossentropy', metrics=['accuracy'])\n",
"\n",
"\n",
"\n",
"history = model.fit(train_images,\n",
" train_labels,\n",
" batch_size=64,\n",
" epochs=100,\n",
" validation_data=(val_images, val_labels),\n",
" )\n"
],
"metadata": {
"id": "PtY0q1p5fM-p"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"## Evaluation du modèle \n",
"test_loss, test_acc = model.evaluate(test_images, test_labels)\n",
"print('Test accuracy:', test_acc)\n",
"\n"
],
"metadata": {
"id": "FcehZmotfPCx"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"## on affiche et on sauvegarde les images\n",
"\n",
"fig, axs = plt.subplots(2, 1, figsize=(15,15))\n",
"\n",
"axs[0].plot(history.history['loss'])\n",
"axs[0].plot(history.history['val_loss'])\n",
"axs[0].title.set_text('Training Loss vs Validation Loss')\n",
"axs[0].legend(['Train', 'Val'])\n",
"\n",
"axs[1].plot(history.history['accuracy'])\n",
"axs[1].plot(history.history['val_accuracy'])\n",
"axs[1].title.set_text('Training Accuracy vs Validation Accuracy')\n",
"axs[1].legend(['Train', 'Val'])\n",
"plt.savefig('./resnet18snake.png')"
],
"metadata": {
"id": "8USwL2YTfRGN"
},
"execution_count": null,
"outputs": []
}
]
}

Cargando…
Cancelar
Guardar