web-dev-qa-db-fra.com

Comment utiliser correctement le processus gaussien de scikit-learn pour une régression à entrées 2D, sortie 1D?

Avant de poster, j'ai fait beaucoup de recherches et trouvé cette question qui pourrait être exactement mon problème. Cependant, j'ai essayé ce qui est proposé dans la réponse, mais malheureusement cela ne l'a pas corrigé, et je n'ai pas pu ajouter de commentaire pour demander des explications supplémentaires, car je suis un nouveau membre ici.

Quoi qu'il en soit, je veux utiliser les processus gaussiens avec scikit-learn dans Python sur un cas simple mais réel pour commencer (en utilisant les exemples fournis dans la documentation de scikit-learn). J'ai un jeu d'entrée 2D (8 couples de 2 paramètres) appelés [~ # ~] x [~ # ~] . J'ai 8 sorties correspondantes, rassemblées dans le tableau 1D y .

#  Inputs: 8 points 
X = np.array([[p1, q1],[p2, q2],[p3, q3],[p4, q4],[p5, q5],[p6, q6],[p7, q7],[p8, q8]])

# Observations: 8 couples
y = np.array([r1,r2,r3,r4,r5,r6,r7,r8])

J'ai défini un espace de test d'entrée x :

# Input space
x1 = np.linspace(x1min, x1max) #p
x2 = np.linspace(x2min, x2max) #q
x = (np.array([x1, x2])).T

Ensuite, j'instancie le modèle GP, je l'adapte à mes données d'entraînement (X, y) , et je fais la prédiction 1D y_pred sur mon espace d'entrée x :

from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, ConstantKernel as C

kernel = C(1.0, (1e-3, 1e3)) * RBF([5,5], (1e-2, 1e2))
gp = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=15)
gp.fit(X, y)
y_pred, MSE = gp.predict(x, return_std=True)

Et puis je fais un tracé 3D:

fig = pl.figure()
ax = fig.add_subplot(111, projection='3d')
Xp, Yp = np.meshgrid(x1, x2)
Zp = np.reshape(y_pred,50)

surf = ax.plot_surface(Xp, Yp, Zp, rstride=1, cstride=1, cmap=cm.jet,
linewidth=0, antialiased=False)
pl.show()

Voici ce que j'obtiens:

RBF[5,5]

Lorsque je modifie les paramètres du noyau, j'obtiens quelque chose comme ceci, similaire à ce que l'affiche que j'ai mentionnée ci-dessus:

RBF[10,10]

Ces graphiques ne correspondent même pas à l'observation des points d'entraînement d'origine (la réponse la plus faible est obtenue pour [65.1,37] et la plus élevée pour [92.3,54]).

Je suis assez nouveau dans les GPs en 2D (également commencé Python il n'y a pas longtemps) donc je pense qu'il me manque quelque chose ici ... Toute réponse serait utile et grandement appréciée, merci!

23
Julie

Vous utilisez deux fonctionnalités pour prédire une troisième. Plutôt qu'un tracé 3D comme plot_surface, il est généralement plus clair si vous utilisez un tracé 2D capable d'afficher des informations sur une troisième dimension, comme hist2d ou pcolormesh. Voici un exemple complet utilisant des données/code similaire à celui de la question:

from itertools import product
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, ConstantKernel as C

X = np.array([[0,0],[2,0],[4,0],[6,0],[8,0],[10,0],[12,0],[14,0],[16,0],[0,2],
                    [2,2],[4,2],[6,2],[8,2],[10,2],[12,2],[14,2],[16,2]])

y = np.array([-54,-60,-62,-64,-66,-68,-70,-72,-74,-60,-62,-64,-66,
                    -68,-70,-72,-74,-76])

# Input space
x1 = np.linspace(X[:,0].min(), X[:,0].max()) #p
x2 = np.linspace(X[:,1].min(), X[:,1].max()) #q
x = (np.array([x1, x2])).T

kernel = C(1.0, (1e-3, 1e3)) * RBF([5,5], (1e-2, 1e2))
gp = GaussianProcessRegressor(kernel=kernel, n_restarts_optimizer=15)

gp.fit(X, y)

x1x2 = np.array(list(product(x1, x2)))
y_pred, MSE = gp.predict(x1x2, return_std=True)

X0p, X1p = x1x2[:,0].reshape(50,50), x1x2[:,1].reshape(50,50)
Zp = np.reshape(y_pred,(50,50))

# alternative way to generate equivalent X0p, X1p, Zp
# X0p, X1p = np.meshgrid(x1, x2)
# Zp = [gp.predict([(X0p[i, j], X1p[i, j]) for i in range(X0p.shape[0])]) for j in range(X0p.shape[1])]
# Zp = np.array(Zp).T

fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111)
ax.pcolormesh(X0p, X1p, Zp)

plt.show()

Production:

enter image description here

Un peu simple, mais mes données d'exemple l'étaient aussi. En général, vous ne devriez pas vous attendre à obtenir un résultat particulièrement intéressant avec ces quelques points de données.

De plus, si vous voulez le tracé de surface, vous pouvez simplement remplacer la ligne pcolormesh par ce que vous aviez à l'origine (plus ou moins):

ax = fig.add_subplot(111, projection='3d')            
surf = ax.plot_surface(X0p, X1p, Zp, rstride=1, cstride=1, cmap='jet', linewidth=0, antialiased=False)

Production:

enter image description here

6
tel

Je suis également assez nouveau en utilisant le processus gaussien scikit-learn. Mais après quelques efforts, j'ai réussi à implémenter avec succès une régression de processus gaussienne 3D. Il existe de nombreux exemples de régression 1-d mais rien sur des dimensions d'entrée plus élevées.

Vous pourriez peut-être afficher les valeurs que vous utilisez.

J'ai trouvé que parfois le format dans lequel vous envoyez les entrées peut produire des problèmes. Essayez de formater l'entrée X comme:

X = np.array([param1, param2]).T

et formatez la sortie comme:

gp.fit(X, y.reshape(-1,1))

Aussi, si j'ai bien compris, la mise en œuvre suppose une fonction moyenne m = 0. Si la sortie que vous essayez de régresser présente une valeur moyenne qui diffère considérablement de 0, vous devez la normaliser (cela résoudra probablement votre problème). La normalisation de l'espace des paramètres sera également utile.

7
Argantonio65