Il existe un livre intitulé "Deep Learning from scratch The Theory and Implementation of Deep Learning appris avec Python". Je l'ai lu deux fois, mais je pense le comprendre, je ne le comprends pas. Depuis qu'il est implémenté en Python en premier lieu, en tant que développeur Java, je pense qu'il a été dupé. En raison du typage dynamique, les arguments de la même méthode sont parfois des nombres et parfois des tableaux, en fonction de ce que l'appelant passe ... trop délicat ... ~~ Ce que vous devez apprendre sur Deeplearning4j docilement ~~ "Oui, implémentons-le en Java". Veuillez vous référer au livre pour l'explication car il est seulement implémenté.
Est-il possible d'implémenter la différenciation et le gradient en Java en premier lieu (P97 4.3 Différenciation numérique / P03 4.4 Gradient)? Si je ne peux pas le faire, je ne pense pas que cela va arriver, alors je l'ai essayé pour le moment (Java 8 ou plus récent).
ArrayUtil.java
private static double h = 1e-4; //Très petit nombre
public double numericalDiff(DoubleUnaryOperator func, double x){
return (func.applyAsDouble(x + h) - func.applyAsDouble(x-h))/ (2*h);
}
Le contenu du test est P103. C'est comme le livre, donc c'est considéré comme bon.
ArrayUtilTest.java
@Test
public void numericalDiff1(){
assertThat(target.numericalDiff(p-> p*p+4*4, 3.0), is(6.00000000000378));
assertThat(target.numericalDiff(p-> 3*3+p*p, 4.0), is(7.999999999999119));
}
Implémentation de la P104 du livre. ~~ Dans l'implémentation du livre (Python), la valeur d'origine est affectée à tmp_val, et après le calcul, elle est renvoyée à la valeur d'origine. Cependant, si vous le faites en Java, les données d'origine changeront après tout car la destination de référence est la même. Par conséquent, une copie complète est utilisée pour contenir les données d'origine. ~~ → J'ai reçu un commentaire disant qu'il n'y a pas de problème si je calcule immédiatement après la substitution. C'est raisonnable.
ArrayUtil.java
private static double h = 1e-4; //Très petit nombre
public double[][] numericalGradient(ToDoubleFunction<double[][]> func, double[][] x){
int cntRow = x.length;
int cntCol = x[0].length;
double[][] result = new double[cntRow][cntCol];
for (int i=0; i < cntRow; i++){
for (int j=0; j < cntCol; j++){
double[][] xPlus = deepCopy(x);
xPlus[i][j] = xPlus[i][j] + h;
double[][] xMinus = deepCopy(x);
xMinus[i][j] = xMinus[i][j] - h;
result[i][j] = (func.applyAsDouble(xPlus) - func.applyAsDouble(xMinus))/ (2*h);
}
}
return result;
}
public double[][] deepCopy(double[][] x){
double[][] copy = new double[x.length][];
for (int i = 0; i < copy.length; i++){
copy[i] = new double[x[i].length];
System.arraycopy(x[i], 0, copy[i], 0, x[i].length);
}
return copy;
}
Le contenu du test est P104. De même, il est considéré comme bon car il est conforme au livre.
ArrayUtilTest.java
@Test
public void numericalGradient(){
ToDoubleFunction<double[][]> function = p-> p[0][0] * p[0][0] + p[0][1]*p[0][1];
double[][] x = {{3,4}};
double[][] result = target.numericalGradient(function, x);
assertThat(result[0][0], is(6.00000000000378));
assertThat(result[0][1], is(7.999999999999119));
result = target.numericalGradient(function, new double[][]{{0,2}});
assertThat(result[0][0], is(closeTo(0.0, 0.000001)));
assertThat(result[0][1], is(closeTo(4.0, 0.000001)));
}
La différenciation et la différenciation partielle semblent convenir. Au fait, je les ai tous mis en œuvre. Le problème est que le PC est lent et je ne peux pas vérifier s'il produit enfin des résultats corrects ouz