Questo spero si tratti l'inizio di alcuni post sulla possibilita' di usare Tensorflow per stimare la concentrazione di alcune specie chimiche partendo da spettri IR
Per questo scopo c'e' bisogno di un database in cui sono presenti spettri IR ed analisi composizionali del materiale. L'unico database pubblico che conosco e' usgs_splib07
da questo link
Per semplicita' sono stati selezionati gli spettri a 480 bande
| | SiO2 | Al2O3 | MgO |
1 | Actinolite HS116 | 57,8 | 0,22 | 22,4 |
2 | Actinolite HS22 | 54,5 | 1,64 | 21,69 |
3 | Actinolite HS315 | 57,7 | 1,38 | 24,58 |
4 | Albite NMNHC5390 | 68,18 | 20,07 | 0,02 |
5 | Almandine HS114 | 40,4 | 22,97 | 0,53 |
6 | Almandine WS475 | 37,98 | 22,14 | 7,35 |
7 | Almandine WS476 | 39,84 | 22,04 | 10,69 |
8 | Almandine WS478 | 39,09 | 22,05 | 5,74 |
9 | Almandine WS479 | 37,34 | 21,93 | 8,83 |
10 | Andradite NMNH113829 | 35,5 | 0,29 | 0,14 |
11 | Andradite WS474 | 35,85 | 0,085 | 0,67 |
12 | Annite WS661 | 33,48 | 14,51 | 0,006 |
13 | Antigorite NMNH96917a | 41,3 | 1,59 | 36,3 |
14 | Augite NMNH120049 | 48,93 | 8,44 | 14,37 |
15 | Biotite WS660 | 39,52 | 11,05 | 14,45 |
16 | Chlorite SMR-13 | 31 | 17,3 | 30,2 |
17 | Clinochlore GDS158 | 27,5 | 19,8 | 24,7 |
18 | Clinochlore GDS159 | 31,3 | 19,4 | 34,7 |
19 | Clinochlore NMNH83369 | 32 | 16 | 33,9 |
20 | Diopside NMNHR18685 | 54,77 | 0,49 | 18,26 |
21 | Elbaite NMNH94217 | 36,83 | 40,56 | 0,03 |
22 | Epidote GDS26 | 37,14 | 23,05 | 0,06 |
23 | Grossular NMNH155371 | 38,84 | 17,95 | 0,15 |
24 | Grossular WS484 | 39,71 | 22,58 | 0,019 |
25 | Halloysite CM13 | 46,3 | 35,2 | 0,31 |
26 | Hectorite SHCa-1 | 34,7 | 0,69 | 15,3 |
27 | Hydrogrossular NMNH120555 | 31,44 | 21,4 | 0,17 |
28 | Hypersthene NMNHC2368 | 51,32 | 4,89 | 26,09 |
29 | Illite GDS4 (Marblehead) | 51,62 | 23,96 | 3,83 |
30 | Illite IMt-1 | 52,1 | 21,9 | 2,39 |
31 | Kaolinite CM5 | 44,4 | 37,9 | 0,11 |
32 | Kaolinite CM7 | 44,6 | 36,4 | 0,14 |
33 | Kaolinite CM9 | 47,1 | 37,4 | 0,16 |
34 | Kaolinite KGa-1 (wxl) | 45 | 38 | 0,02 |
35 | Kaolinite KGa-2 (pxl) | 44,2 | 37,2 | 0,04 |
36 | Lizardite NMNHR4687 | 40,97 | 0 | 40,43 |
37 | Marialite NMNH126018-2 | 59,88 | 20,59 | 0 |
38 | Meionite WS701 | 49,6 | 25,45 | 0,06 |
39 | Mizzonite NMNH113775 | 49,6 | 25,43 | 0,03 |
40 | Montmorillonite CM20 | 52 | 18,36 | 3,32 |
41 | Montmorillonite CM26 | 63,4 | 18,2 | 2,26 |
42 | Montmorillonite CM27 | 57,6 | 20,9 | 2,66 |
43 | Montmorillonite+Illite CM37 | 46,5 | 22,7 | 2,74 |
44 | Montmorillonite+Illite CM42 | 54,8 | 21 | 3,4 |
45 | Montmorillonite SAz-1 | 60,4 | 17,6 | 6,46 |
46 | Montmorillonite SCa-2 | 52,4 | 15 | 6,68 |
47 | Montmorillonite STx-1 | 69,6 | 16,3 | 3,56 |
48 | Montmorillonite SWy-1 | 62,9 | 19,3 | 2,8 |
49 | Muscovite GDS108 | 44 | 35 | 0,57 |
50 | Nontronite NG-1 | 80 | 2 | 0,42 |
51 | Nontronite SWa-1 | 74,6 | 7,69 | 3,32 |
52 | Olivine GDS70 Fo89 | 41,09 | 0 | 49,29 |
53 | Olivine GDS71 Fo91 | 40,06 | 0 | 50,7 |
54 | Olivine KI3005 Fo11 | 30,11 | 0 | 4,42 |
55 | Olivine KI3054 Fo66 | 36,3 | 0 | 32,62 |
56 | Olivine KI3188 Fo51 | 34,34 | 0 | 23,8 |
57 | Olivine KI3189 Fo60 | 35,47 | 0 | 29,49 |
58 | Palygorskite CM46a | 56 | 10,6 | 8,56 |
59 | Pectolite NMNH94865 | 53,37 | 0,03 | 0,03 |
60 | Phlogopite GDS20 | 40,3 | 14,3 | 26,4 |
61 | Phlogopite WS496 | 43,015 | 11,6 | 29,62 |
62 | Quartz HS117 Aventurine | 100 | 0 | 0 |
63 | Rhodonite NMNHC6148 | 46,3 | 0,05 | 0,41 |
64 | Richterite NMNH150800 | 54,87 | 1,97 | 22,92 |
65 | Saponite SapCa-1 | 51,9 | 3,66 | 0,88 |
66 | Sepiolite SepNev-1.AcB | 50,9 | 0,45 | 22,3 |
67 | Talc HS21 | 60,47 | 0,12 | 30,29 |
68 | Talc WS659 | 58,38 | 0,18 | 31,9 |
69 | Thuringite SMR-15 | 24,7 | 21,1 | 16,8 |
70 | Tremolite NMNH117611 | 54,6 | 1,88 | 23,13 |
71 | Vermiculite VTx-1.a | 19,5 | 1,53 | 27,7 |
I dati sono stati estratti dalla directory ASCIIData/ASCIIdata_splib07a/ChapterM_Minerals selezionando gli spettri denominati BECKb_AREF.
Un esempio di file e'
---------------------------------------
splib07a Record=120: Actinolite HS116.3B BECKb AREF
-1.2300000e+034
3.3700544e-002
3.5717472e-002
3.5481069e-002
3.5344660e-002
3.4786128e-002
3.3701397e-002
3.3403333e-002
3.3196956e-002
3.3779550e-002
3.2682978e-002
3.3049587e-002
3.4390874e-002
3.4718834e-002
3.6168687e-002
...............................................
---------------------------------------
Si iniziano quindi a preparare i dati per inserirli in un array compatibile con NumPy,formato idoneo al successivo utilizzo con Tensorflow
per prima cosa si toglie la prima riga di intestazione con sed
for f in *.txt ; do sed -i '1d' $f; done
viene quindi eseguito uno script python che legge i dati riga per riga e restituisce una stringa lineare con i dati separati da un punto e virgola
converti.py
=================================
with open("1.txt",'r') as f:
while True:
buf = f.readline()
if not buf:
break
print (buf.strip()),
print ';',
=================================
for f in *.txt ; do python converti.py > a$f; done
i nuovi file avranno il carattere a anteposto al precedente nome file
for f in *.txt ; do python converti.py > a$f; done
si tolgono quindi gli spazi bianchi
for f in a*.txt ; do cat $f | tr - d "[:space:]" > b$f ; done
i nuovi file avranno il carattere b anteposto al precedente nome file
siamo quasi arrivati alla fine. Ogni file dello spettro e' costituito da un riga, si deve quindi creare un unico file in cui ogni riga rappresenta uno spettro
for f in ba*.txt; do (cat "${f}"; echo) >> completo.txt; done
from numpy import genfromtxt
data = genfromtxt('completo.txt', delimiter=',')
Da notare bene che tensorflow non funziona su macchine con processori non recenti perche' vengono usate delle istruzioni cpu recenti (
AVX and AVX2 instruction sets)
Per installare Tensorflow su Debian con virtualenv si usa la sequenza (ripresa da
questo sito)
si installa python3
apt-get install python3-venv python3
mkdir spectra
cd spectra
python3 -m venv venv
source venv/bin/activate
pip install --upgrade pip
pip install --upgrade tensorflow
per verificare l'installazione si usa
python -c 'import tensorflow as tf; print(tf.__version__)'
per terminare virtualenv si digita
deactivate
A questo punto ho diviso il file di 71 spettri in una serie di train di 60 spettri ed una serie di test di 11 spettri (x_train,x_test) . Per quanto riguarda le concentrazioni il file delle concentrazioni (y_train, y_test) i valori di concentrazioni sono stati divisi in 10 classi con la seguente regola
0-9.9% : classe 0
10-19.9% : classe 1
20-29.9% : classe 2
30-39.9% : classe 3
40-49.9% : classe 4
50-59.9% : classe 5
60-69.9% : classe 6
70-79.9% : classe 7
80-89.9% : classe 8
90-100% : classe 9
per prova ho usato le concentrazioni di SiO2 (uno dei parametri piu' difficili da determinare da uno spettro IR nel rilevamento iperspettrale)
Prima di procedere i valori No data contenuti negli spettri e indicati dal valore
-1.2300000e+034 sono stati convertiti in 0
provando con un rete neurale con delle impostazioni non ottimizzate
==============================================================
import numpy as np
from numpy import genfromtxt
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
x_train = genfromtxt("x_train.txt",delimiter=';',usecols=np.arange(0,479))
x_test = genfromtxt("x_test.txt",delimiter=';',usecols=np.arange(0,479))
y_train = genfromtxt("y_train.txt",delimiter=';',usecols=np.arange(0,1))
y_test = genfromtxt("y_test.txt",delimiter=';',usecols=np.arange(0,1))
y_train = y_train.transpose()
#print (x_train)
y_train = y_train.astype(int)
y_test = y_test.astype(int)
#print (y_train)
print ("====================")
print ("X trains" + str(x_train.shape))
print ("Y trains" + str(y_train.shape))
print ("X test" + str(x_test.shape))
print ("Y test" + str(y_test.shape))
print ("====================")
model = tf.keras.Sequential()
model.add(layers.Dense(128,activation='relu'))
model.add(layers.Dropout(0.2))
model.add(layers.Dense(10,activation='softmax'))
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])
model.fit(x_train,y_train,epochs=16)
model.evaluate(x_test,y_test,verbose=2)
==============================================================
il risultato e' il seguente
====================
X trains(60, 479)
Y trains(60,)
X test(11, 479)
Y test(11,)
====================
2019-11-15 13:35:58.075622: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2019-11-15 13:35:58.099810: I tensorflow/core/platform/profile_utils/cpu_utils.cc:94] CPU Frequency: 2294770000 Hz
2019-11-15 13:35:58.100500: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x38bfc90 executing computations on platform Host. Devices:
2019-11-15 13:35:58.100551: I tensorflow/compiler/xla/service/service.cc:175] StreamExecutor device (0): Host, Default Version
Train on 60 samples
Epoch 1/16
60/60 [==============================] - 0s 8ms/sample - loss: 2.2551 - accuracy: 0.1000
Epoch 2/16
60/60 [==============================] - 0s 85us/sample - loss: 1.7444 - accuracy: 0.3833
Epoch 3/16
60/60 [==============================] - 0s 90us/sample - loss: 1.6373 - accuracy: 0.3333
Epoch 4/16
60/60 [==============================] - 0s 83us/sample - loss: 1.6465 - accuracy: 0.3167
Epoch 5/16
60/60 [==============================] - 0s 96us/sample - loss: 1.5436 - accuracy: 0.3833
Epoch 6/16
60/60 [==============================] - 0s 127us/sample - loss: 1.6167 - accuracy: 0.3667
Epoch 7/16
60/60 [==============================] - 0s 92us/sample - loss: 1.4574 - accuracy: 0.3833
Epoch 8/16
60/60 [==============================] - 0s 100us/sample - loss: 1.5219 - accuracy: 0.3500
Epoch 9/16
60/60 [==============================] - 0s 81us/sample - loss: 1.4713 - accuracy: 0.4000
Epoch 10/16
60/60 [==============================] - 0s 81us/sample - loss: 1.4284 - accuracy: 0.3500
Epoch 11/16
60/60 [==============================] - 0s 105us/sample - loss: 1.4529 - accuracy: 0.4167
Epoch 12/16
60/60 [==============================] - 0s 107us/sample - loss: 1.3913 - accuracy: 0.4167
Epoch 13/16
60/60 [==============================] - 0s 92us/sample - loss: 1.4574 - accuracy: 0.4000
Epoch 14/16
60/60 [==============================] - 0s 82us/sample - loss: 1.4370 - accuracy: 0.3500
Epoch 15/16
60/60 [==============================] - 0s 80us/sample - loss: 1.4666 - accuracy: 0.3667
Epoch 16/16
60/60 [==============================] - 0s 88us/sample - loss: 1.3726 - accuracy: 0.4500
11/1 - 0s - loss: 3.1148 - accuracy: 0.0000e+00
Impiegando i dati di concentrazione di Mg0 le cose migliorano
60/60 [==============================] - 1s 9ms/sample - loss: 1.8941 - accuracy: 0.3833
Epoch 2/16
60/60 [==============================] - 0s 194us/sample - loss: 1.4062 - accuracy: 0.6500
Epoch 3/16
60/60 [==============================] - 0s 167us/sample - loss: 1.1572 - accuracy: 0.6500
Epoch 4/16
60/60 [==============================] - 0s 187us/sample - loss: 1.1490 - accuracy: 0.6333
Epoch 5/16
60/60 [==============================] - 0s 173us/sample - loss: 1.0612 - accuracy: 0.6333
Epoch 6/16
60/60 [==============================] - 0s 195us/sample - loss: 1.0615 - accuracy: 0.6500
Epoch 7/16
60/60 [==============================] - 0s 193us/sample - loss: 1.0023 - accuracy: 0.6333
Epoch 8/16
60/60 [==============================] - 0s 164us/sample - loss: 1.0067 - accuracy: 0.6667
Epoch 9/16
60/60 [==============================] - 0s 221us/sample - loss: 0.9609 - accuracy: 0.6667
Epoch 10/16
60/60 [==============================] - 0s 185us/sample - loss: 0.9922 - accuracy: 0.6333
Epoch 11/16
60/60 [==============================] - 0s 163us/sample - loss: 0.9188 - accuracy: 0.6333
Epoch 12/16
60/60 [==============================] - 0s 234us/sample - loss: 0.9704 - accuracy: 0.6333
Epoch 13/16
60/60 [==============================] - 0s 176us/sample - loss: 0.9234 - accuracy: 0.6833
Epoch 14/16
60/60 [==============================] - 0s 202us/sample - loss: 0.9051 - accuracy: 0.6833
Epoch 15/16
60/60 [==============================] - 0s 181us/sample - loss: 0.8635 - accuracy: 0.7167
Epoch 16/16
60/60 [==============================] - 0s 171us/sample - loss: 0.8449 - accuracy: 0.7000
11/1 - 0s - loss: 2.3372 - accuracy: 0.2727