Es gibt ein Buch mit dem Titel "Deep Learning von Grund auf neu Die Theorie und Implementierung von Deep Learning, das mit Python gelernt wurde". Ich habe es zweimal gelesen, aber ich glaube, ich verstehe es, ich verstehe es nicht. Da es als Java-Entwickler in erster Linie in Python implementiert ist, habe ich das Gefühl, dass es getäuscht wurde. Aufgrund der dynamischen Typisierung sind die Argumente derselben Methode manchmal Zahlen und manchmal Arrays, je nachdem, was der Aufrufer übergibt ... zu knifflig ... ~~ Was Sie gehorsam über Deeplearning4j lernen sollten ~~ "Ja, lassen Sie es uns in Java implementieren". Weitere Informationen finden Sie im Buch, da es nur implementiert ist.
Ist es überhaupt möglich, Differenzierung und Gradienten in Java zu implementieren (P97 4.3 Numerische Differenzierung / P03 4.4 Gradient)? Wenn ich es nicht kann, denke ich nicht, dass es passieren wird, also habe ich es vorerst versucht (Java 8 oder höher).
ArrayUtil.java
private static double h = 1e-4; //Sehr kleine Anzahl
public double numericalDiff(DoubleUnaryOperator func, double x){
return (func.applyAsDouble(x + h) - func.applyAsDouble(x-h))/ (2*h);
}
Der Inhalt des Tests ist P103. Es ist genau wie das Buch, also gilt es als gut.
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));
}
P104 des Buches implementiert. ~~ In der Buchimplementierung (Python) wird der ursprüngliche Wert tmp_val zugewiesen und nach der Berechnung auf den ursprünglichen Wert zurückgesetzt. Wenn Sie dies jedoch in Java tun, ändern sich die Originaldaten schließlich, da das Referenzziel dasselbe ist. Daher wird eine tiefe Kopie verwendet, um die Originaldaten zu speichern. ~~ → Ich habe einen Kommentar erhalten, dass es kein Problem gibt, wenn ich sofort nach der Substitution berechne. Es ist vernünftig.
ArrayUtil.java
private static double h = 1e-4; //Sehr kleine Anzahl
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;
}
Der Inhalt des Tests ist P104. Ebenso wird es als gut angesehen, weil es dem Buch entspricht.
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)));
}
Differenzierung und teilweise Differenzierung scheinen in Ordnung zu sein. Übrigens habe ich alle implementiert. Das Problem ist, dass der PC langsam ist und ich nicht überprüfen kann, ob er endlich die richtigen Ergebnisse ausgibt oder
Recommended Posts