Repository navigation
Pickling state / pickling whole class issue #6
Description
Activity
Hello,
the question sounds very interesting and is also very relevant for me.I would also like to do the calculation, the fit separately from the predict method, among other things also because the calculation takes some time. Based on the previous post, I have adapted an example to show my approach. I would be grateful for any hints on how to do it correctly.
from pyTsetlinMachine.tm import MultiClassTsetlinMachine from pyTsetlinMachine.tools import Binarizer import numpy as np from sklearn import datasets from sklearn.model_selection import train_test_split import pickle import pickletools breast_cancer = datasets.load_breast_cancer() X = breast_cancer.data Y = breast_cancer.target b = Binarizer(max_bits_per_feature = 10) b.fit(X) X_transformed = b.transform(X) tm = MultiClassTsetlinMachine(800, 40, 5.0) print("\nMean accuracy over 10 runs:\n") tm_results = np.empty(0) for i in range(5): X_train, X_test, Y_train, Y_test = train_test_split(X_transformed, Y, test_size=0.2) tm.fit(X_train, Y_train, epochs=25) with open('dat_' + str(i) + '.pickle', 'wb') as handle: p = pickle.dump(tm.get_state(), handle, protocol=pickle.HIGHEST_PROTOCOL) #pickletools.dis(p) tm_results = np.append(tm_results, np.array(100*(tm.predict(X_test) == Y_test).mean())) print("#%d Average Accuracy: %.2f%% +/- %.2f" % (i+1, tm_results.mean(), 1.96*tm_results.std()/np.sqrt(i+1))) for i in range(5): with open('dat_' + str(i) + '.pickle','rb') as pickle_file: state= pickle.load(pickle_file) tm2 = MultiClassTsetlinMachine(800, 40, 5.0) tm2.set_state(state) tm2_results = np.append(tm_results, np.array(100*(tm2.predict(X_test) == Y_test).mean())) print("#%d Average Accuracy: %.2f%% +/- %.2f" % (i+1, tm2_results.mean(), 1.96*tm2_results.std()/np.sqrt(i+1)))My error message:
Mean accuracy over 10 runs:
File "/mnt/c/ProjectsGit/tm-segment/BreastCancerDemo_pkl.py", line 42, in <module> tm2.set_state(state) File "/home/unix/miniconda3/lib/python3.8/site-packages/pyTsetlinMachine/tm.py", line 351, in set_state for i in range(self.number_of_classes): AttributeError: 'MultiClassTsetlinMachine' object has no attribute 'number_of_classes'Just to link things together, that last post is now asked over at StackOverflow:
https://stackoverflow.com/q/66099424/10495893Hi @bmreiniger and @andife! Thanks for bringing up this issue.
The get- and set state methods only operate on the state of the Tsetlin Automata from the C-part of the code.
It is the fit-function on the Python side that sets the other crucial parameters and creates the actual Tsetlin Machine structure in C, if self.mc_tm == None:if self.mc_tm == None: self.number_of_classes = int(np.max(Y) + 1) if self.append_negated: self.number_of_features = X.shape[1]*2 else: self.number_of_features = X.shape[1] self.number_of_patches = 1 self.number_of_ta_chunks = int((self.number_of_features-1)/32 + 1) self.mc_tm = _lib.CreateMultiClassTsetlinMachine(self.number_of_classes, self.number_of_clauses, self.number_of_features, 1, self.number_of_ta_chunks, self.number_of_state_bits, self.T, self.s, self.s_range, self.boost_true_positive_feedback, self.weighted_clauses)As you see from the above code, the number of features and classes is obtained automatically from the input data X and Y. So, one possible trick is to call fit on the training data first, with epochs=0. Then fit will set the number of classes and features and create the TM in C, without running any epochs over the data. After calling fit, you can call set_state to initialize the Tsetlin Automata from the saved state.
I am planning to add methods for this. Let me know if it works out!
Reacted by Jie LeiHello @olegranmo, @bmreiniger;
Thanks for the solution for this issue. It works! (I used the code below for testing)
In general, I'm wondering if I really need/should load the original dataset, or if it's not a synthetic one that just contains the same number of features and classes. This would also correspond to the approach of https://github.com/cair/pyTsetlinMachine/pull/4/files.
from pyTsetlinMachine.tm import MultiClassTsetlinMachine from pyTsetlinMachine.tools import Binarizer import numpy as np from sklearn import datasets from sklearn.model_selection import train_test_split import pickle import pickletools breast_cancer = datasets.load_breast_cancer() X = breast_cancer.data Y = breast_cancer.target b = Binarizer(max_bits_per_feature = 10) b.fit(X) X_transformed = b.transform(X) tm = MultiClassTsetlinMachine(800, 40, 5.0) print("\nMean accuracy over 10 runs:\n") tm_results = np.empty(0) tm2_results = np.empty(0) for i in range(5): X_train, X_test, Y_train, Y_test = train_test_split(X_transformed, Y, test_size=0.2,random_state=i) tm.fit(X_train, Y_train, epochs=25) with open('dat_' + str(i) + '.pickle', 'wb') as handle: p = pickle.dump(tm.get_state(), handle, protocol=pickle.HIGHEST_PROTOCOL) #pickletools.dis(p) tm_results = np.append(tm_results, np.array(100*(tm.predict(X_test) == Y_test).mean())) print("#%d Average Accuracy: %.2f%% +/- %.2f" % (i+1, tm_results.mean(), 1.96*tm_results.std()/np.sqrt(i+1))) del tm for i in range(5): with open('dat_' + str(i) + '.pickle','rb') as pickle_file: state = pickle.load(pickle_file) X2_train, X2_test, Y2_train, Y2_test = train_test_split(X_transformed, Y, test_size=0.2,random_state=i) #X2_train = X2_train + 100 tm2 = MultiClassTsetlinMachine(800, 40, 5.0) tm2.fit(X_train, Y_train, epochs=0) # X_train does not change, only for setting the correct dimensions tm2.set_state(state) tm2_results = np.append(tm2_results, np.array(100*(tm2.predict(X2_test) == Y2_test).mean())) print("sec2 #%d Average Accuracy: %.2f%% +/- %.2f" % (i+1, tm2_results.mean(), 1.96*tm2_results.std()/np.sqrt(i+1)))Great that it works, @andife! Yes, I guess you could for instance just use one example X with the correct number of features and the largest y-value (number of classes - 1).
@olegranmo It seems this approach is not working for CUDA version.
For following script (Parallel version):from pyTsetlinMachineParallel.tm import MultiClassTsetlinMachine import numpy as np from time import time from keras.datasets import mnist import pickle (X_train, Y_train), (X_test, Y_test) = mnist.load_data() X_train = np.where(X_train.reshape((X_train.shape[0], 28*28)) > 75, 1, 0) X_test = np.where(X_test.reshape((X_test.shape[0], 28*28)) > 75, 1, 0) tm = MultiClassTsetlinMachine(2000, 50, 10.0) print("\nAccuracy over 10 epochs:\n") for i in range(10): start_training = time() tm.fit(X_train, Y_train, epochs=1, incremental=True) stop_training = time() start_testing = time() result = 100*(tm.predict(X_test) == Y_test).mean() stop_testing = time() print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing)) print("Saving TM state...") with open('tm001.pkl', 'wb') as handle: pickle.dump(tm.get_state(), handle, protocol=pickle.HIGHEST_PROTOCOL) print("Loading TM state...") tm2 = MultiClassTsetlinMachine(2000, 50, 10.0) tm2.fit(X_train, Y_train, epochs=0) with open('tm001.pkl','rb') as pickle_file: state = pickle.load(pickle_file) tm2.set_state(state) print("Continue training") for i in range(5): start_training = time() tm2.fit(X_train, Y_train, epochs=1, incremental=True) stop_training = time() start_testing = time() result = 100*(tm2.predict(X_test) == Y_test).mean() stop_testing = time() print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing))results of reloaded TM are the same as at the end of training:
Accuracy over 10 epochs:#1 Accuracy: 94.27% Training: 35.89s Testing: 21.07s
#2 Accuracy: 95.53% Training: 26.94s Testing: 21.09s
#3 Accuracy: 95.97% Training: 25.63s Testing: 21.27s
#4 Accuracy: 96.56% Training: 24.98s Testing: 21.72s
#5 Accuracy: 96.72% Training: 24.10s Testing: 21.48s
#6 Accuracy: 96.77% Training: 23.22s Testing: 21.47s
#7 Accuracy: 96.88% Training: 23.08s Testing: 21.86s
#8 Accuracy: 96.87% Training: 22.60s Testing: 21.47s
#9 Accuracy: 97.10% Training: 22.38s Testing: 21.59s
#10 Accuracy: 97.16% Training: 22.14s Testing: 21.63s
Saving TM state...
Loading TM state...
Continue training
#1 Accuracy: 97.18% Training: 21.44s Testing: 21.19s
#2 Accuracy: 97.25% Training: 21.31s Testing: 21.22s
#3 Accuracy: 97.22% Training: 20.92s Testing: 20.78s
#4 Accuracy: 97.10% Training: 21.36s Testing: 21.17s
#5 Accuracy: 97.49% Training: 20.65s Testing: 21.22sbut for CUDA version:
from PyTsetlinMachineCUDA.tm import MultiClassTsetlinMachine import numpy as np from time import time from keras.datasets import mnist import pickle (X_train, Y_train), (X_test, Y_test) = mnist.load_data() X_train = np.where(X_train.reshape((X_train.shape[0], 28*28)) > 75, 1, 0) X_test = np.where(X_test.reshape((X_test.shape[0], 28*28)) > 75, 1, 0) tm = MultiClassTsetlinMachine(2000, 50*16, 10.0, max_weight=16) print("\nAccuracy over 10 epochs:\n") for i in range(10): start_training = time() tm.fit(X_train, Y_train, epochs=1, incremental=True) stop_training = time() start_testing = time() result = 100*(tm.predict(X_test) == Y_test).mean() stop_testing = time() print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing)) print("Saving TM state...") with open('tm002.pkl', 'wb') as handle: pickle.dump(tm.get_state(), handle, protocol=pickle.HIGHEST_PROTOCOL) print("Loading TM state...") tm2 = MultiClassTsetlinMachine(2000, 50*16, 10.0, max_weight=16) tm2.fit(X_train, Y_train, epochs=0) with open('tm002.pkl','rb') as pickle_file: state = pickle.load(pickle_file) tm2.set_state(state) print("Continue training") for i in range(5): start_training = time() tm2.fit(X_train, Y_train, epochs=1, incremental=True) stop_training = time() start_testing = time() result = 100*(tm2.predict(X_test) == Y_test).mean() stop_testing = time() print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing))there is no effect after reload, it's like script is starting from zero:
Accuracy over 10 epochs:#1 Accuracy: 92.80% Training: 9.59s Testing: 1.08s
#2 Accuracy: 94.21% Training: 8.10s Testing: 1.15s
#3 Accuracy: 95.56% Training: 7.85s Testing: 1.07s
#4 Accuracy: 96.01% Training: 7.44s Testing: 1.07s
#5 Accuracy: 96.38% Training: 7.38s Testing: 1.07s
#6 Accuracy: 96.61% Training: 7.63s Testing: 1.12s
#7 Accuracy: 96.69% Training: 7.79s Testing: 1.13s
#8 Accuracy: 96.94% Training: 7.74s Testing: 1.14s
#9 Accuracy: 97.06% Training: 7.50s Testing: 1.14s
#10 Accuracy: 97.09% Training: 7.80s Testing: 1.06s
Saving TM state...
Loading TM state...
Continue training
#1 Accuracy: 92.97% Training: 9.77s Testing: 1.02s
#2 Accuracy: 94.23% Training: 8.06s Testing: 1.15s
#3 Accuracy: 95.66% Training: 8.17s Testing: 1.14s
#4 Accuracy: 96.08% Training: 7.42s Testing: 1.06s
#5 Accuracy: 96.56% Training: 7.88s Testing: 1.06sHi @devop01 - thanks for reporting! I have started adding pickle support, just completed for PyTsetlinMachine.
Hi again @devop01, just added pickle support for PyTsetlinMachineCUDA!
Hi @olegranmo
Thank you for new version :)
I reinstalled it, and results of training after loading a pickle didn't improve unfortunately.
I'm not sure if this is issue with my CUDA setup, or something else is missing.
Comparison of TM before and after a pickle could improve investigation, so I think overriding eq
operator could be helpful.Accuracy over 25 epochs:
#1 Accuracy: 92.89% Training: 9.78s Testing: 1.06s
#2 Accuracy: 94.30% Training: 7.76s Testing: 1.11s
#3 Accuracy: 95.64% Training: 7.80s Testing: 1.10s
#4 Accuracy: 96.06% Training: 7.67s Testing: 1.10s
#5 Accuracy: 96.37% Training: 7.62s Testing: 1.11s
#6 Accuracy: 96.67% Training: 7.89s Testing: 1.15s
#7 Accuracy: 96.77% Training: 7.79s Testing: 1.10s
#8 Accuracy: 96.95% Training: 7.57s Testing: 1.11s
#9 Accuracy: 97.06% Training: 7.54s Testing: 1.09s
#10 Accuracy: 97.23% Training: 7.50s Testing: 1.09s
#11 Accuracy: 97.23% Training: 7.47s Testing: 1.09s
#12 Accuracy: 97.32% Training: 7.46s Testing: 1.14s
#13 Accuracy: 97.36% Training: 7.70s Testing: 1.14s
#14 Accuracy: 97.48% Training: 7.62s Testing: 1.09s
#15 Accuracy: 97.54% Training: 7.40s Testing: 1.08s
#16 Accuracy: 97.60% Training: 7.40s Testing: 1.09s
#17 Accuracy: 97.54% Training: 7.39s Testing: 1.09s
#18 Accuracy: 97.53% Training: 7.38s Testing: 1.09s
#19 Accuracy: 97.60% Training: 7.38s Testing: 1.09s
#20 Accuracy: 97.50% Training: 7.37s Testing: 1.09s
#21 Accuracy: 97.63% Training: 7.37s Testing: 1.09s
#22 Accuracy: 97.75% Training: 7.37s Testing: 1.09s
#23 Accuracy: 97.70% Training: 7.36s Testing: 1.09s
#24 Accuracy: 97.67% Training: 7.36s Testing: 1.09s
#25 Accuracy: 97.70% Training: 7.37s Testing: 1.09s
Saving TM state...
Loading TM state...
Comparing tm1 and tm2
False
Continue training
#1 Accuracy: 92.95% Training: 9.86s Testing: 1.05s
#2 Accuracy: 94.16% Training: 7.77s Testing: 1.11s
#3 Accuracy: 95.64% Training: 7.83s Testing: 1.10s
#4 Accuracy: 96.21% Training: 7.70s Testing: 1.10s
#5 Accuracy: 96.43% Training: 7.63s Testing: 1.10sBelow is a full code I used:
from PyTsetlinMachineCUDA.tm import MultiClassTsetlinMachine import numpy as np from time import time from keras.datasets import mnist import pickle (X_train, Y_train), (X_test, Y_test) = mnist.load_data() X_train = np.where(X_train.reshape((X_train.shape[0], 28*28)) > 75, 1, 0) X_test = np.where(X_test.reshape((X_test.shape[0], 28*28)) > 75, 1, 0) tm = MultiClassTsetlinMachine(2000, 50*16, 10.0, max_weight=16) print("\nAccuracy over 25 epochs:\n") for i in range(25): start_training = time() tm.fit(X_train, Y_train, epochs=1, incremental=True) stop_training = time() start_testing = time() result = 100*(tm.predict(X_test) == Y_test).mean() stop_testing = time() print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing)) print("Saving TM state...") with open('tm005.pkl', 'wb') as handle: pickle.dump(tm, handle, protocol=pickle.HIGHEST_PROTOCOL) print("Loading TM state...") with open('tm005.pkl','rb') as pickle_file: tm2 = pickle.load(pickle_file) print("Comparing tm1 and tm2") print(tm == tm2) print("Continue training") for i in range(5): start_training = time() tm2.fit(X_train, Y_train, epochs=1, incremental=True) stop_training = time() start_testing = time() result = 100*(tm2.predict(X_test) == Y_test).mean() stop_testing = time() print("#%d Accuracy: %.2f%% Training: %.2fs Testing: %.2fs" % (i+1, result, stop_training-start_training, stop_testing-start_testing))Hi @devop01, this happens because the local voting tallies used for asynchronous parallel learning is not stored as part of the state. Everything is reinitialized when you start training again. Will fix this in the next update!
As far as I understand there are problems with saving state of learned TM.
This is important for research development, as checkpoint can be created in a easy way.
I tried to pickle MultiClassTsetlinMachine (from pyTsetlinMachineParallel.tm ) as well as pyCUDA version and both failed.
Then I tried to pickle just TM state (from MNIST example):
eg:
tm = MultiClassTsetlinMachine(2000, 50, 10.0)
f = open..
pickle.dump(tm.get_state(),f)
#new session
f = open...
state = pickle.load(f)
tm2 = MultiClassTsetlinMachine(2000, 50, 10.0)
tm2.set_state(state)
Result:
Traceback (most recent call last):
File "<pyshell#15>", line 1, in
tm.set_state(state)
File "/.../TsetlinMachine/pyTsetlinMachineParallel/tm.py", line 314, in set_state
for i in range(self.number_of_classes):
AttributeError: 'MultiClassTsetlinMachine' object has no attribute 'number_of_classes'
if I update number of classes:
tm2.number_of_classes = 10
tm2.set_state(state)
program hangs, and after some time I got:
=============================== RESTART: Shell ===============================