Gelades Objekt ungleich abgespeichertes Objekt (Subtiler Fehler?)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
CoolRabi
User
Beiträge: 1
Registriert: Freitag 24. Februar 2023, 19:56

Moin, ein Student von mir hat ein etwas subtiles Problem mit seinem Code und wir sind uns nicht sicher, wo der Fehler liegt. Daher wende ich mich an euch :)
Folgendes Problem:
Wir speichern in einem Skript ein Objekt einer Klasse ab (ein Vektorquantisierer). Dann, in einem anderen Skript, welches im Allgemeinen auch auf einem anderen Rechner läuft (die Skripte laufen bei uns im Rechencluster), wird dieses Objekt wieder geladen.
Das Objekt hat, welches geladen wird, unterscheidet sich hin und wieder leicht vom abgespeicherten Objekt. Ich hege derzeit die Vermutung, dass es daran liegt, dass auf i.A. unterschiedlichen Computern gespeichert und geladen wird. Hier die relevanten Codezeilen:

Code: Alles auswählen

class VectorQuantizer(Quantizer):
    def __init__(self, bits, dim):
        Quantizer.__init__(self, bits)
        self.n_init=5
        self.algorithm = 'full'
        self.kmeans = None
        self.clusters = 2**bits
        self.dim = dim

    def encode(self, data):
        code = self.kmeans.predict(data.astype(float))
        return code

    def decode(self, data):
        data = data.astype(int)
        dqdata = self.kmeans.cluster_centers_[data]
        return dqdata

    def train(self, data):
        self.kmeans = MiniBatchKMeans(n_clusters=self.clusters, batch_size=1024)
        self.kmeans.fit(data)
    
    def getFlattenedWeights(self):
        return self.kmeans.cluster_centers_.flatten()

    def setWeights(self, weights):
        cc = weights.reshape(self.clusters, self.dim)
        self.kmeans.cluster_centers_ = cc

    def load(self, savepath, name=''):
        savename = 'vquant_' + str(self.bits) + name 
        with open(os.path.join(savepath, savename + '.pkl'), 'rb') as f:
            tmp_dict = pickle.load(f)
        self.__dict__.update(tmp_dict)

    def save(self, savepath, name=''):
        savename = 'vquant_' + str(self.bits) + name 
        with open(os.path.join(savepath, savename + '.pkl'), 'wb') as f:
            pickle.dump(self.__dict__, f)
    
Beim Speichern eines VectorQuantizer Objekts kommt es zu unterschieden zwischen dem abgespeicherten und dem geladenen Objekt.
Ist das Abspeichern wie es hier vorgenommen wird zusammen mit der Ladefunktion robust gegenüber Wechsel des Computersystems?
Hatte jemand schon mal ein ähnliches Problem und hat ggf. Ideen worauf man schauen könnte?

Vielen Dank für jede Anregung :)
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wie genau äussert sich sich denn der oder die Unterschiede?
Benutzeravatar
__blackjack__
User
Beiträge: 14065
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@CoolRabi: Es kann eventuell sein, dass nicht der komplette Zustand in `__dict__` gespeichert wird, falls `Quantizer` (oder eine weitere Basisklasse in der Hirarchie) `__slots__` verwendet, oder in C implementiert ist und Zustand auf andere Art und Weise speichert.

Die API ist auch nicht gut, dass man erst ein `VectorQuantizer`-Objekt mit Dummy-Argumenten erstellen muss, um darauf dann die `load()`-Methode aufzurufen, die versucht den Dummy-Zustand durch den aus der Datei zu ersetzen. Da würde man als API eher eine Klassenmethode erwarten, die eine Datei direkt als `VectorQuantizer` als Rückgabewert liefert.

Und hast Du sichergestellt, dass das Speichern/Laden die Ursache ist? Kann es sein, dass beim erstellen eines solchen Objekts auch ein bisschen Zufall mit hinein spielt? Also das sich zwei mit gleichen Daten erstellte Objekte auch ohne Laden und Speichern nicht 100-prozentig gleichen? Die Startpunkte für KMeans-Clustering könnten ja beispielsweise zufällig gewählt werden.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten