Upload files to "sources"
This commit is contained in:
parent
5313d95f1f
commit
9b7ad97417
1 changed files with 284 additions and 0 deletions
284
sources/keras_facile.py
Normal file
284
sources/keras_facile.py
Normal file
|
|
@ -0,0 +1,284 @@
|
|||
##########################################
|
||||
##### Module : keras_facile #####
|
||||
##### #####
|
||||
##### Auteur : Arnaud Bodin #####
|
||||
##### Date : Janvier 2020 #####
|
||||
##########################################
|
||||
|
||||
import tensorflow as tf
|
||||
import numpy as np
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
from mpl_toolkits.mplot3d import Axes3D
|
||||
|
||||
from tensorflow import keras
|
||||
from tensorflow.keras.models import Sequential
|
||||
from tensorflow.keras.layers import Input, Dense
|
||||
|
||||
|
||||
# Fonction d'activation Heaviside
|
||||
from tensorflow.keras import backend as K
|
||||
def heaviside(x):
|
||||
""" Définis la fonction de Heaviside qui n'est pas défini
|
||||
par défaut dans keras. A utiliser comme fonction
|
||||
d'activiation lors de la définition d'une couche par exemple
|
||||
modele.add(Dense(4,activation=heaviside))
|
||||
Attention il n'y a pas de guillemet ici.
|
||||
Astuce de la formule : H(x) = 1/2 (1+|x|) """
|
||||
|
||||
# return (1+x/K.abs(x))/2
|
||||
# return (1+K.sign(x))/2
|
||||
|
||||
z = K.zeros_like(x)
|
||||
return 1-K.maximum(z,K.sign(-x))
|
||||
|
||||
|
||||
# Affichage des poids
|
||||
def affiche_poids(modele,couche):
|
||||
""" Affiches les informations d'un couche donnée :
|
||||
- nb de neurones, nb d'entrée, nb de poids par neurones.
|
||||
Puis pour chaque neurone, affiche du poids : coeff + biais. """
|
||||
|
||||
|
||||
coeff, biais = modele.layers[couche].get_weights()
|
||||
nb_entrees = len(coeff)
|
||||
nb_neurones = len(coeff[0])
|
||||
print("\n\n===== Couche numéro",couche,"=====")
|
||||
print("Nombre de neurones :",nb_neurones)
|
||||
print("Nombre d'entrées par neurones :",nb_entrees)
|
||||
print("Nombre de poids par neurones :",nb_entrees+1,"\n")
|
||||
for i in range(nb_neurones):
|
||||
print(" --- Neurone numéro",i,"---")
|
||||
print(' Coefficients',np.transpose(coeff)[i])
|
||||
print(' Biais',biais[i])
|
||||
return
|
||||
|
||||
|
||||
# Mettre tous les poids à zéros (purement esthétique)
|
||||
def poids_a_zeros(modele,couche):
|
||||
""" Met tous les poids à zéros d'une couche.
|
||||
C'est par soucis esthétique car lors de la définition d'une couche,
|
||||
les poids initiaux sont des nombres au hasard. """
|
||||
|
||||
coeff, biais = modele.layers[couche].get_weights()
|
||||
newcoeff = np.zeros(np.shape(coeff))
|
||||
newbiais = np.zeros(np.shape(biais))
|
||||
newpoids = [newcoeff,newbiais]
|
||||
modele.layers[couche].set_weights(newpoids)
|
||||
return
|
||||
|
||||
# Définir les poids d'un neurone à la main
|
||||
def definir_poids(modele,couche,rang,ncoeff,nbiais):
|
||||
""" Définis les poids d'un neurone.
|
||||
Le neurone est identifié par la couche et le rang dans cette couche.
|
||||
ncoeff : les coefficients à définir pour le neurone,
|
||||
cela peut être un réel (si un seul coeff), une liste de réels,
|
||||
ou un vecteur numpy.
|
||||
nbiais : un réel
|
||||
Exemples :
|
||||
definir_poids(modele,0,2,7,3) # si une entrée
|
||||
definir_poids(modele,0,2,[7,-2],3) # si deux entrées (ou plus)
|
||||
definir_poids(modele,0,2,vecteur,3) # où vecteur est vecteur numpy
|
||||
"""
|
||||
|
||||
# Récupérer les poids actuels
|
||||
coeff, biais = modele.layers[couche].get_weights()
|
||||
|
||||
# Changer le biais d'un neurone
|
||||
biais[rang] = nbiais
|
||||
|
||||
#Chager les coeff d'un neurone
|
||||
if isinstance(ncoeff, (int, float, complex)): # cas d'une seule valeur
|
||||
ncoeff = [ncoeff] # x devient [x]
|
||||
|
||||
if isinstance(ncoeff, list):
|
||||
ncoeff = np.array(ncoeff) # Transforme liste en array si besoin
|
||||
|
||||
nb_entrees = len(coeff)
|
||||
for i in range(nb_entrees):
|
||||
coeff[i,rang] = ncoeff[i]
|
||||
newpoids = [coeff,biais]
|
||||
modele.layers[couche].set_weights(newpoids)
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Evaluation d'un réseau (variante de predict())
|
||||
def evaluation(modele,*entree):
|
||||
""" Renvoie le résultat calculer par le réseau de neurones en fonction de l'entrée.
|
||||
'entree' peut être un réel (si un seul coeff), une liste de réels,
|
||||
ou un vecteur numpy.
|
||||
Exemples :
|
||||
evaluation(modele,7) # une entrée
|
||||
evaluation(modele,[10,5,7]) # deux entrée ou plus (ici trois)
|
||||
evaluation(modele,vecteur) # avec vecteur numpy """
|
||||
|
||||
# Cas x ou x,y ou x,y,z
|
||||
if isinstance(entree[0], (int, float, complex)):
|
||||
entree = list(entree)
|
||||
else:
|
||||
entree = entree[0]
|
||||
|
||||
# predict doit recevoir tableau numpy type [[x,y,z]]
|
||||
entree = np.array([entree])
|
||||
sortie = modele.predict(entree)
|
||||
if len(sortie)==1:
|
||||
sortie = sortie[0]
|
||||
return sortie[0]
|
||||
|
||||
|
||||
# Graphique une variable
|
||||
def affichage_evaluation_une_var(modele,a,b,rang=0,num=100):
|
||||
""" Affichage graphique dans le cas où une seul entrée au réseau.
|
||||
La fonction associée au neurone dont le rang est donné (par défaut le premier neurone)
|
||||
est tracée sur l'intervalle [a,b], divisé en n """
|
||||
# Affichage graphique
|
||||
liste_x = np.linspace(a, b, num=num)
|
||||
entree = np.array([[x] for x in liste_x])
|
||||
sortie = modele.predict(entree)
|
||||
liste_y = np.array([y[rang] for y in sortie])
|
||||
plt.plot(liste_x,liste_y)
|
||||
plt.tight_layout()
|
||||
# plt.savefig('pythontf-1var.png')
|
||||
plt.show()
|
||||
|
||||
|
||||
# Graphique du théorème d'approximation universel
|
||||
def affichage_approximation(modele,f,a,b,rang=0,num=100):
|
||||
""" Comme 'affichage_evaluation_une_var'
|
||||
mais affiche en plus le graphe de f """
|
||||
liste_x = np.linspace(a, b, num=num)
|
||||
entree = np.array([[x] for x in liste_x])
|
||||
sortie = modele.predict(entree)
|
||||
liste_y = np.array([y[rang] for y in sortie])
|
||||
plt.plot(liste_x,f(liste_x),color='red')
|
||||
plt.plot(liste_x,liste_y,color='blue',linewidth=2)
|
||||
plt.tight_layout()
|
||||
# plt.savefig('pythontf-approx.png')
|
||||
plt.show()
|
||||
|
||||
|
||||
# Définis un réseau qui approxime une fonction
|
||||
def calcul_approximation(modele,f,a,b,n):
|
||||
# calcule et définis les poids
|
||||
|
||||
# Couche 0 : 2*n neurones
|
||||
h = (b-a)/n
|
||||
x = a
|
||||
xx = a+h
|
||||
liste_y = []
|
||||
for i in range(n):
|
||||
definir_poids(modele,0,2*i,1/x,-1)
|
||||
definir_poids(modele,0,2*i+1,-1/xx,1)
|
||||
|
||||
y = f(x)
|
||||
liste_y = liste_y + [y,y]
|
||||
|
||||
x = x + h
|
||||
xx = xx + h
|
||||
|
||||
# Couche 1 : un seul neurone
|
||||
definir_poids(modele,1,0,liste_y,-sum(liste_y)/2)
|
||||
return
|
||||
|
||||
|
||||
# Graphique 3d deux variables
|
||||
def affichage_evaluation_deux_var_3d(modele,xmin,xmax,ymin,ymax,rang=0,num=20):
|
||||
""" Affichage graphique dans le cas où une seul entrée au réseau.
|
||||
La fonction associée au neurone dont le rang est donnée (par défaut le premier neurone)
|
||||
est tracée sur la zone [xmin,xmax]x[ymin,ymax], divisé en n """
|
||||
|
||||
VX = np.linspace(xmin, xmax, num)
|
||||
VY = np.linspace(ymin, ymax, num)
|
||||
|
||||
X,Y = np.meshgrid(VX, VY)
|
||||
|
||||
entree = np.c_[X.ravel(), Y.ravel()]
|
||||
|
||||
sortie = modele.predict(entree)
|
||||
Z = sortie.reshape(X.shape)
|
||||
|
||||
fig = plt.figure()
|
||||
ax = plt.axes(projection='3d')
|
||||
ax.set_xlabel('axe x')
|
||||
ax.set_ylabel('axe y')
|
||||
ax.set_zlabel('axe z')
|
||||
|
||||
ax.plot_surface(X, Y, Z)
|
||||
|
||||
plt.tight_layout()
|
||||
# ax.view_init(50, -110)
|
||||
# plt.savefig('pythontf-2var-3d.png')
|
||||
plt.show()
|
||||
|
||||
return
|
||||
|
||||
# Graphique 2d deux variables
|
||||
def affichage_evaluation_deux_var_2d(modele,xmin,xmax,ymin,ymax,rang=0,num=30,niveaux=10):
|
||||
""" Affichage graphique dans le cas où une seul entrée au réseau.
|
||||
La fonction associée au neurone dont le rang est donnée (par défaut le premier neurone)
|
||||
est tracée sur la zone [xmin,xmax]x[ymin,ymax], divisé en n """
|
||||
|
||||
VX = np.linspace(xmin, xmax, num)
|
||||
VY = np.linspace(ymin, ymax, num)
|
||||
|
||||
X,Y = np.meshgrid(VX, VY)
|
||||
entree = np.c_[X.ravel(), Y.ravel()]
|
||||
|
||||
sortie = modele.predict(entree)
|
||||
Z = sortie.reshape(X.shape)
|
||||
|
||||
fig = plt.figure()
|
||||
|
||||
plt.contourf(X, Y, Z,niveaux, cmap='hot')
|
||||
plt.colorbar();
|
||||
plt.axis('equal')
|
||||
plt.tight_layout()
|
||||
# plt.savefig('pythontf-2var-2d.png')
|
||||
plt.show()
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Graphique 3d trois variables
|
||||
def affichage_evaluation_trois_var(modele,xmin,xmax,ymin,ymax,zmin,zmax,rang=0,num=10):
|
||||
""" Affichage graphique dans le cas où une seul entrée au réseau.
|
||||
La fonction associée au neurone dont le rang est donnée (par défaut le premier neurone)
|
||||
est tracée sur la zone [xmin,xmax]x[ymin,ymax], divisé en n """
|
||||
|
||||
VX = np.linspace(xmin, xmax, num)
|
||||
VY = np.linspace(ymin, ymax, num)
|
||||
VZ = np.linspace(zmin, zmax, num)
|
||||
|
||||
X,Y,Z = np.meshgrid(VX, VY, VZ)
|
||||
entree = np.c_[X.ravel(), Y.ravel(), Z.ravel()]
|
||||
|
||||
sortie = modele.predict(entree)
|
||||
S = sortie.reshape(X.shape)
|
||||
|
||||
fig = plt.figure()
|
||||
ax = plt.axes(projection='3d')
|
||||
ax.set_xlabel('axe x')
|
||||
ax.set_ylabel('axe y')
|
||||
ax.set_zlabel('axe z')
|
||||
|
||||
points = ax.scatter(X.ravel(),Y.ravel(),Z.ravel(), c=S.ravel(), cmap='hot')
|
||||
fig.colorbar(points)
|
||||
plt.tight_layout()
|
||||
# ax.view_init(20, 55)
|
||||
# plt.savefig('pythontf-3var.png')
|
||||
plt.show()
|
||||
|
||||
return
|
||||
|
||||
|
||||
# Références 'mpariente' https://stackoverflow.com/questions/51140950/
|
||||
def get_weights_grad(model, inputs, outputs):
|
||||
""" Gets gradient of model for given inputs and outputs for all weights """
|
||||
grads = model.optimizer.get_gradients(model.total_loss, model.trainable_weights)
|
||||
symb_inputs = (model._feed_inputs + model._feed_targets + model._feed_sample_weights)
|
||||
f = K.function(symb_inputs, grads)
|
||||
x, y, sample_weight = model._standardize_user_data(inputs, outputs)
|
||||
output_grad = f(x + y + sample_weight)
|
||||
return output_grad
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue