Double Well Potential Symmetry Visualization¶
In this notebook we will perform symmetry group visualization on some double well potential data.
The imports for this one are quite numerous as we are doing the analysis piece by piece. Once there is a bridge between group detection and generator extraction I will add some generalzed methods for doing some of this automatically. Let’s quickly mention what we are importing.
The class for a Double Well Potential. This is just for some test data generation.
DenseModel is a class written to take care of setting up and deploying a neural network.
DataCluster is reponsible for taking raw potential data and partitioning it into classes for the classification problems.
Group detection performs the TSNE reduction and finds our symmetry groups
from symdet.test_systems.double_well_potential import DoubleWellPotential from symdet.models.dense_model import DenseModel from symdet.symmetry_groups.data_clustering import DataCluster from symdet.symmetry_groups.group_detection import GroupDetection
[1]:
import symdet
Preparing data¶
So you want to prepare some simple data from a double well potential so that we can identify some symmetry groups. Luckily, we were prepared for this scenario and wrote a class just for you!
[2]:
double_well_potential = symdet.DoubleWellPotential(a=2.4)
As simple as that we have a double well potential. But we can also take a look at it.
[3]:
double_well_potential.plot_data()
Preparing the classes¶
We now have to cluster the data to set up the machine learning problem for later. We define the clusters using the value range and bin operation. In this case we are binning the data in clusters of [ k/5 -1e-3, k/5 + 1e-3 ] with k in [-5, 5]. We will also visualize the clusters on the original data to aid in understanding how it was chosen.
[4]:
double_well_potential.build_clusters(representatives=1500)
Loading additional data.
WARNING: Not enough data! Some classes will be under-represented.
[5]:
double_well_potential.plot_clusters()
100%|████████████████████████████████| 11/11 [00:00<00:00, 418.56it/s]
Preparing the model¶
We want to use a deep and wide neural network so as to encode a high dimensional representation.
[6]:
model = symdet.DenseModel(n_layers=7,
units=80,
epochs=10,
batch_size=64,
lr=0.00025)
Running the analysis¶
The next steps are to define a group detection object with the cluster object we used earlier as well as the model to use in training.
We then simply run the symmetry detection and can visualize the symmetry relationship.
[7]:
sym_detector = symdet.GroupDetection(model, double_well_potential.clustered_data)
point_cloud = sym_detector.run_symmetry_detection(plot=True)
WARNING:tensorflow:Please add `keras.layers.InputLayer` instead of `keras.Input` to Sequential model. `keras.Input` is intended to be used by Functional model.
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 80) 240
_________________________________________________________________
dense_1 (Dense) (None, 80) 6480
_________________________________________________________________
dense_2 (Dense) (None, 80) 6480
_________________________________________________________________
dense_3 (Dense) (None, 80) 6480
_________________________________________________________________
dense_4 (Dense) (None, 80) 6480
_________________________________________________________________
second_last_layer (Dense) (None, 80) 6480
_________________________________________________________________
embedding_layer (Dense) (None, 80) 6480
_________________________________________________________________
softmax_layer (Dense) (None, 11) 891
=================================================================
Total params: 40,011
Trainable params: 40,011
Non-trainable params: 0
_________________________________________________________________
None
Epoch 1/10
129/129 [==============================] - 1s 4ms/step - loss: 2.4226 - acc: 0.1482 - val_loss: 2.3177 - val_acc: 0.2036
Epoch 2/10
129/129 [==============================] - 0s 2ms/step - loss: 2.1419 - acc: 0.2268 - val_loss: 2.0102 - val_acc: 0.3331
Epoch 3/10
129/129 [==============================] - 0s 2ms/step - loss: 1.8410 - acc: 0.3436 - val_loss: 1.6872 - val_acc: 0.3966
Epoch 4/10
129/129 [==============================] - 0s 2ms/step - loss: 1.5227 - acc: 0.4732 - val_loss: 1.3562 - val_acc: 0.4529
Epoch 5/10
129/129 [==============================] - 0s 3ms/step - loss: 1.2672 - acc: 0.5424 - val_loss: 1.1256 - val_acc: 0.6735
Epoch 6/10
129/129 [==============================] - 0s 3ms/step - loss: 1.0367 - acc: 0.6730 - val_loss: 0.9485 - val_acc: 0.7420
Epoch 7/10
129/129 [==============================] - 0s 3ms/step - loss: 0.8745 - acc: 0.7559 - val_loss: 0.8207 - val_acc: 0.7184
Epoch 8/10
129/129 [==============================] - 0s 2ms/step - loss: 0.7606 - acc: 0.7848 - val_loss: 0.6881 - val_acc: 0.8752
Epoch 9/10
129/129 [==============================] - 0s 2ms/step - loss: 0.6591 - acc: 0.8636 - val_loss: 0.6292 - val_acc: 0.8329
Epoch 10/10
129/129 [==============================] - 0s 2ms/step - loss: 0.5678 - acc: 0.9095 - val_loss: 0.5377 - val_acc: 0.7844
Epoch 1/10
129/129 [==============================] - 0s 3ms/step - loss: 0.5137 - acc: 0.9145 - val_loss: 0.4918 - val_acc: 0.9731
Epoch 2/10
129/129 [==============================] - 0s 3ms/step - loss: 0.4400 - acc: 0.9625 - val_loss: 0.4139 - val_acc: 0.9535
Epoch 3/10
129/129 [==============================] - 0s 2ms/step - loss: 0.3975 - acc: 0.9596 - val_loss: 0.3705 - val_acc: 0.9885
Epoch 4/10
129/129 [==============================] - 0s 2ms/step - loss: 0.3569 - acc: 0.9629 - val_loss: 0.3056 - val_acc: 1.0000
Epoch 5/10
129/129 [==============================] - 0s 2ms/step - loss: 0.3296 - acc: 0.9627 - val_loss: 0.2729 - val_acc: 1.0000
Epoch 6/10
129/129 [==============================] - 0s 2ms/step - loss: 0.2585 - acc: 0.9994 - val_loss: 0.2397 - val_acc: 1.0000
Epoch 7/10
129/129 [==============================] - 0s 2ms/step - loss: 0.2295 - acc: 0.9977 - val_loss: 0.2214 - val_acc: 1.0000
Epoch 8/10
129/129 [==============================] - 0s 3ms/step - loss: 0.2262 - acc: 0.9770 - val_loss: 0.1767 - val_acc: 1.0000
Epoch 9/10
129/129 [==============================] - 0s 3ms/step - loss: 0.1697 - acc: 1.0000 - val_loss: 0.1605 - val_acc: 1.0000
Epoch 10/10
129/129 [==============================] - 0s 2ms/step - loss: 0.1484 - acc: 1.0000 - val_loss: 0.1371 - val_acc: 1.0000
Epoch 1/10
129/129 [==============================] - 0s 2ms/step - loss: 0.1326 - acc: 1.0000 - val_loss: 0.1210 - val_acc: 1.0000
Epoch 2/10
129/129 [==============================] - 0s 2ms/step - loss: 0.1149 - acc: 1.0000 - val_loss: 0.1093 - val_acc: 1.0000
Epoch 3/10
129/129 [==============================] - 0s 2ms/step - loss: 0.1034 - acc: 1.0000 - val_loss: 0.1115 - val_acc: 1.0000
Epoch 4/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0923 - acc: 1.0000 - val_loss: 0.0858 - val_acc: 1.0000
Epoch 5/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0831 - acc: 1.0000 - val_loss: 0.0780 - val_acc: 1.0000
Epoch 6/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0754 - acc: 1.0000 - val_loss: 0.0712 - val_acc: 1.0000
Epoch 7/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0695 - acc: 1.0000 - val_loss: 0.0682 - val_acc: 1.0000
Epoch 8/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0647 - acc: 1.0000 - val_loss: 0.0621 - val_acc: 1.0000
Epoch 9/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0607 - acc: 1.0000 - val_loss: 0.0585 - val_acc: 1.0000
Epoch 10/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0580 - acc: 1.0000 - val_loss: 0.0572 - val_acc: 1.0000
Epoch 1/10
129/129 [==============================] - 0s 3ms/step - loss: 0.0553 - acc: 1.0000 - val_loss: 0.0543 - val_acc: 1.0000
Epoch 2/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0526 - acc: 1.0000 - val_loss: 0.0516 - val_acc: 1.0000
Epoch 3/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0510 - acc: 1.0000 - val_loss: 0.0498 - val_acc: 1.0000
Epoch 4/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0491 - acc: 1.0000 - val_loss: 0.0493 - val_acc: 1.0000
Epoch 5/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0475 - acc: 1.0000 - val_loss: 0.0467 - val_acc: 1.0000
Epoch 6/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0460 - acc: 1.0000 - val_loss: 0.0455 - val_acc: 1.0000
Epoch 7/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0449 - acc: 1.0000 - val_loss: 0.0441 - val_acc: 1.0000
Epoch 8/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0436 - acc: 1.0000 - val_loss: 0.0430 - val_acc: 1.0000
Epoch 9/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0426 - acc: 1.0000 - val_loss: 0.0420 - val_acc: 1.0000
Epoch 10/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0416 - acc: 1.0000 - val_loss: 0.0409 - val_acc: 1.0000
Epoch 1/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0406 - acc: 1.0000 - val_loss: 0.0402 - val_acc: 1.0000
Epoch 2/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0397 - acc: 1.0000 - val_loss: 0.0392 - val_acc: 1.0000
Epoch 3/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0388 - acc: 1.0000 - val_loss: 0.0384 - val_acc: 1.0000
Epoch 4/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0381 - acc: 1.0000 - val_loss: 0.0376 - val_acc: 1.0000
Epoch 5/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0372 - acc: 1.0000 - val_loss: 0.0368 - val_acc: 1.0000
Epoch 6/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0363 - acc: 1.0000 - val_loss: 0.0358 - val_acc: 1.0000
Epoch 7/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0355 - acc: 1.0000 - val_loss: 0.0350 - val_acc: 1.0000
Epoch 8/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0346 - acc: 1.0000 - val_loss: 0.0342 - val_acc: 1.0000
Epoch 9/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0338 - acc: 1.0000 - val_loss: 0.0334 - val_acc: 1.0000
Epoch 10/10
129/129 [==============================] - 0s 2ms/step - loss: 0.0330 - acc: 1.0000 - val_loss: 0.0325 - val_acc: 1.0000
WARNING:tensorflow:Please add `keras.layers.InputLayer` instead of `keras.Input` to Sequential model. `keras.Input` is intended to be used by Functional model.
So now we can analyze our model! We see for the darker colours that there are always two distinct instances corresponding to the symmetry between these radial values. The duplication of these colours means that this is a symmetry group. The test now is to identify the radial values in these clusters and pass them to the generator extraction methods to characterize them.
[8]:
point_cloud.keys()
[8]:
dict_keys([0.0, 1.0, 3.0, 5.0])
We see that the clustering has worked relatively well. This is where some caution is advised in terms of simply parsing this data along to the generator detection. If you see that one of these groups should likely not be in the set then it should be parsed along to the generator extraction stage. Alternatively, you can use a different approach for identifying the sets in the symmetry representation. In the next update we will parse this data to the generator extraction algorithm in order to get the generators of this detected symmetry group.