1

Ich habe ein Tupel. Das erste Element ist ein Float und das zweite ist eine Liste mit verschachtelten Listen, die Floats enthalten (machen Sie sich keine Gedanken darüber, was diese Werte bedeuten).Warum ändern sich meine Tupelwerte (Python)?

(0.2742965753780876, [[[33.119], [-8.326]], [[-34.084, -4.385], [-3.047, 18.546], [-10.757, 0.573], [21.395, 23.937], [5.011, -5.234]], [[-23.434, 9.989, 9.113, -23.253, 11.86], [-56.818, 4.771, -3.383, -27.143, 4.81], [-6.564, -40.132, -2.223, -2.663, -10.231], [-2.05, -15.989, 4.369, -20.051, 4.657]], [[-10.868, -39.934, 0.465, 38.103]], [-0.889, 1.129, 0.743]]) 
(0.2742965753780876, [[[21.633], [-8.972]], [[-35.754, -13.243], [-0.718, 17.724], [-16.452, 6.619], [24.151, 25.037], [1.76, -7.891]], [[-26.011, 9.072, 14.685, -20.044, 10.612], [-55.53, -0.131, 0.15, -27.031, 8.03], [-3.225, -36.499, -2.558, 0.253, -8.292], [-1.274, -22.561, 0.431, -23.405, 6.808]], [[-13.668, -47.758, -6.489, 43.27]], [-0.889, 1.129, 0.743]]) 
(0.2742965753780876, [[[22.435], [-6.71]], [[-47.591, -8.998], [-1.134, 16.529], [-16.399, 4.369], [23.344, 24.72], [2.175, -14.129]], [[-26.603, 11.472, 9.433, -21.13, 9.759], [-50.109, 1.084, 1.256, -18.826, 9.588], [-6.935, -27.957, 9.045, 1.291, 2.27], [-1.336, -29.908, -0.3, -27.242, 4.555]], [[-12.933, -42.377, 4.077, 38.864]], [-0.889, 1.129, 0.743]]) 
(0.2742965753780876, [[[26.688], [-4.315]], [[-49.478, -4.214], [0.116, 20.39], [-14.691, 3.496], [15.367, 23.116], [18.075, -2.748]], [[-25.588, 6.249, 4.364, -20.727, 19.639], [-55.524, -2.901, 4.639, -11.759, 11.794], [-8.633, -25.316, 11.841, 1.492, 1.36], [-0.797, -26.306, 1.379, -16.266, -0.291]], [[-24.726, -46.726, 12.765, 38.977]], [-0.889, 1.129, 0.743]]) 
(0.2742965753780876, [[[21.776], [-8.466]], [[-47.66, -5.868], [1.855, 23.062], [-19.521, 18.331], [29.251, 25.491], [21.32, -5.379]], [[-36.199, 7.786, -1.48, -27.042, 14.769], [-61.468, -12.218, -10.307, -6.156, 8.287], [-17.785, -33.124, 16.564, 2.249, -0.675], [-4.391, -18.11, 7.349, -9.234, -2.31]], [[-23.139, -55.043, 9.106, 35.827]], [-0.889, 1.129, 0.743]]) 

Diese Werte wurden durch einen genetischen Algorithmus erhalten, der künstliche neuronale Netze trainiert. Wie Sie sehen können, habe ich fünf Generationen des Top-Tupels gepostet. Wenn Sie mit ML vertraut sind, werden Sie bemerken, dass das erste Element der mittlere quadratische Fehler ist, den das ANN beim Klassifizieren der Trainingsdaten erzeugt, und das zweite Element die Liste der Gewichte im ANN ist, die diesem Fehler zugeordnet sind.

Jedes Mal, wenn ich eine neue Generation erstelle, nehme ich die obersten Tupel und "lege sie zurück" in eine Liste neuer Kandidaten, weshalb der obige Fehler mehrmals auftrat. Es war der beste Kandidat in jeder Generation.

Sie müssen dies jedoch nicht wissen, um mein Problem zu verstehen.

Was wichtig ist, ist, dass jedes Mal, wenn ich eine neue Generation mit meiner genetischen Algorithmusfunktion durchführe, der oberste Fehler (erstes Element) sich nicht ändert. Das ist normal, weil der Algorithmus keine bessere Lösung gefunden hat. Und natürlich sollten sich die Gewichte (zweites Element) auch nicht ändern, weil sie andernfalls einen völlig anderen Fehler ergeben würden.

Leider ist dies nicht der Fall. Die Daten in meinem Tupel werden irgendwie geändert. Wie Sie im obigen Ausdruck sehen können, bleibt der Fehler bei jedem Durchlauf einer neuen Generation gleich, aber die Gewichte ändern sich.

Warum könnte das sein? Warum ändert sich ein Wert in einem Tupel?

Hier ist ein Blick auf meinen Code. Dies ist der Code zum Generieren von Mutationen. Die muate() - Methode durchläuft die Liste der Gewichtungen (Floats) und führt kleine, zufällige Inkremente für diese Gewichtungen durch. Dies ist, was es zu 0.2742965753780876 macht, obwohl es nicht sein sollte, weil es keinen Sinn macht, die Gewichte zu ändern und den Fehler nicht zu aktualisieren. Und es sollte nicht einmal möglich sein, weil Tupel unveränderlich sind.

for i in range(10): 
    mList = weightList[random.randint(0,4)][1] # pick a set of weights from the top 5 
    newList = mutate(mList, weightList[0][0]) # create a new list by mutating certain values of the unmutated list 
    n.setWeights(listToGenome(newList,n)) # give the ANN the new weights 
    error = trainSine(n) # train the network on the training set and return the mean-squared error 
weightList.append((error, child)) 

Sie können auch wissen wollen, dass jedes Mal, wenn ich bin eine neue Generation getan zu schaffen, ich die Listen durch ihre Fehler sortieren und die Top-Ten-Kandidaten wählt in die nächste Generation fortzusetzen.

errorList.sort() 
for i in range(10): 
    survivorList.append(errorList[i]) 

Das ist es. Es gibt natürlich viel mehr Code, aber ich werde es teilen, wenn jemand es braucht. Irgendwelche Ideen?

+6

Ihre enthaltenen Listen sind * noch veränderbare Objekte *, und Sie teilen sie zwischen Tupeln. Sie müssen stattdessen (tiefe?) Kopien von ihnen erstellen. –

+2

Randnotiz: Anstatt alle Generationen zu sortieren, verwenden Sie einen heapq, um nur die obersten 10 auszuwählen, indem Sie die Funktion '' heapq.nsmallest() '] (https://docs.python.org/2/library/heapq) verwenden .html # heapq.nsmallest): 'survivorList = heapq.nsmallest (10, errorList)'.Dies ist effizienter (O (NlogK) für die heapq Kommissionierung K Elemente vs O (NlogN) für die Sortierung) –

Antwort

6

Tupel sind nicht veränderlich, aber die Listen darin sind immer noch. Sie müssen eine tiefe Kopie der Listen machen, die die Werte zum Zeitpunkt des Kopierens kopiert, ohne alle variablen Referenzen und so weiter. Sie können dies mit dem Modul copy tun. Die Syntax lautet wie folgt:

import copy 
myList = [1, 5, 3, 9, 4] 
myOtherList = copy.deepcopy(myList) 

den oben stehenden Code verwenden, wenn Sie myList ändern, oder wenn eine der Variablen zu myList Veränderung beiträgt, wird myOtherList gleich bleiben, unabhängig von den anderen.

+0

Dies ist genau das, was ich gesucht habe, obwohl es immer noch nicht funktioniert. Meine Werte ändern sich immer noch. Es macht wirklich keinen Sinn für mich, da, wann immer ich ein Tupel erstelle, es immer mit den richtigen Werten ist. – user255919

+0

Ok, ich denke ich hätte es verstanden. Es sieht so aus, als müsste ich eine tiefe Kopie des Parameters in meiner Mutator-Funktion machen, nicht nur eine tiefe Kopie des Wertes, den die Funktion zurückgibt. – user255919

+0

@ user255919 Ich bin froh, Ihnen helfen zu können! :-) –

Verwandte Themen