<jupyter_start><jupyter_text>Reti neurali con Tensor FlowIn questo notebook vengono presentati degli esercizi sulle reti neurali con Tensor Flow.Provate a svolgere il seguente esercizio:1) [pp -> H -> ZZ -> 4lepton](section1)  pp -> H -> ZZ -> 4lepton Creare una rete neurale per analizzare i dati prodotti dagli studi di pp -> H -> ZZ -> 4lepton nel contesto delle ricerche mono-Higgs da parte della collaborazione CMS. I programmi usano le ntuple ridotte (con il nome dell'albero radice HZZ4LeptonsAnalysisReduced) create con Root.<jupyter_code>import uproot
import pandas as pd
import numpy as np
import h5py

# fix random seed for reproducibility
seed = 7
np.random.seed(seed)

treename = 'HZZ4LeptonsAnalysisReduced'

VARS = ['f_mass4l', 'f_massjj']
upfile_VV = uproot.open('data/ntuple_4mu_VV.root')
params_VV = upfile_VV[treename].arrays(VARS, library="np")
upfile_BKG = uproot.open('data/ntuple_4mu_bkg.root')
params_BKG = upfile_BKG[treename].arrays(VARS, library="np")

df_VV = pd.DataFrame(params_VV, columns=VARS)
df_BKG = pd.DataFrame(params_BKG, columns=VARS)
    
# cut out undefined variables VARS[0] and VARS[1] > -999
df_VV = df_VV[(df_VV[VARS[0]] > -999) & (df_VV[VARS[1]] > -999)]
df_BKG = df_BKG[(df_BKG[VARS[0]] > -999) & (df_BKG[VARS[1]] > -999)] 

# add isSignal variable
df_VV['isSignal'] = np.ones(len(df_VV)) 
df_BKG['isSignal'] = np.zeros(len(df_BKG))

df_all = pd.concat([df_VV, df_BKG])
df_all<jupyter_output><empty_output><jupyter_text>Creiamo una rete densa, con un singolo livello nascosto completamente connesso con lo stesso numero di neuroni delle variabili di input.Possiamo quindi usare la funzione di attivazione `sigmoide` per produrre un'uscita di probabilità nell'intervallo da 0 a 1.Infine usiamo la funzione di loss `binary_crossentropy` durante l'allenamento, una funzione di perdita standard per problemi di classificazione binaria.Infine utimmizziamo il modello con l'algoritmo Adam per il grandient descend.<jupyter_code>from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, ReLU

NDIM = len(VARS)
model = Sequential()

model.add(Dense(2, input_dim=2))
model.add(ReLU())
model.add(Dense(units=2))
model.add(ReLU())
model.add(Dense(units=1, activation='sigmoid'))


model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

# print the model summary
model.summary()
X = df_all[VARS]
y = df_all['isSignal']
X<jupyter_output><empty_output><jupyter_text>Procediamo a questo punto a suddividere i dati tra input e test e a effettuare uno scaling:<jupyter_code>from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# preprocessing: standard scalar
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler().fit(x_train)
X_train_val = scaler.transform(x_train)
X_test_val = scaler.transform(x_test)<jupyter_output><empty_output><jupyter_text>Ora facciamo il training:<jupyter_code># early stopping callback
from keras.callbacks import EarlyStopping
early_stopping = EarlyStopping(monitor='val_loss', patience=10)

history = model.fit(X_train_val,
                    y_train,
                    epochs=1000, 
                    verbose=1, # switch to 0 for less verbosity 
                    callbacks=[early_stopping], 
                    validation_data=(X_test_val, y_test))<jupyter_output>Epoch 1/1000
519/519 [==============================] - 0s 908us/step - loss: 0.5235 - accuracy: 0.7814 - val_loss: 0.5244 - val_accuracy: 0.7794
Epoch 2/1000
519/519 [==============================] - 0s 804us/step - loss: 0.5235 - accuracy: 0.7813 - val_loss: 0.5243 - val_accuracy: 0.7799
Epoch 3/1000
519/519 [==============================] - 0s 767us/step - loss: 0.5235 - accuracy: 0.7814 - val_loss: 0.5244 - val_accuracy: 0.7797
Epoch 4/1000
519/519 [==============================] - 0s 778us/step - loss: 0.5235 - accuracy: 0.7814 - val_loss: 0.5243 - val_accuracy: 0.7799
Epoch 5/1000
519/519 [==============================] - 0s 866us/step - loss: 0.5235 - accuracy: 0.7813 - val_loss: 0.5243 - val_accuracy: 0.7799
Epoch 6/1000
519/519 [==============================] - 0s 809us/step - loss: 0.5234 - accuracy: 0.7813 - val_loss: 0.5243 - val_accuracy: 0.7799
Epoch 7/1000
519/519 [==============================] - 0s 793us/step - loss: 0.5235 - accuracy: 0.7812 - val_loss: 0.5244 -[...]<jupyter_text>Stampiamo loss e accuracy:<jupyter_code>import matplotlib.pyplot as plt

# plot loss vs epoch
plt.figure(figsize=(12, 4))
plt.plot(history.history['loss'], label='loss')
plt.plot(history.history['val_loss'], label='val_loss')
plt.legend(loc="upper right")
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

# plot accuracy vs epoch
plt.figure(figsize=(12, 4))
plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label='val_accuracy')
plt.legend(loc="upper left")
plt.xlabel('epoch')
plt.ylabel('acc')
plt.show()<jupyter_output><empty_output><jupyter_text>Vediamo il modello in azione:<jupyter_code>X_val = scaler.transform(X)
df_all['predict'] = model.predict(X_val)

df_all['predict'] = np.around(df_all['predict']).astype(np.int64)
df_all['isSignal'] = np.around(df_all['isSignal']).astype(np.int64)

df_all
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(df_all['isSignal'].array, df_all['predict'].array)
classes = ['No', 'Yes']

fig, ax = plt.subplots()
im = ax.imshow(cm, cmap=plt.cm.Blues)

ax.figure.colorbar(im, ax=ax)
ax.set(xticks=np.arange(cm.shape[1]),
       yticks=np.arange(cm.shape[0]),
       xticklabels=classes,
       yticklabels=classes,
       ylabel='True label',
       xlabel='Predicted label')

for i in range(cm.shape[0]):
    for j in range(cm.shape[1]):
        ax.text(j, i, format(cm[i, j], 'd'),
                ha="center", va="center",
                color="white" if cm[i, j] > cm.max() / 2. else "black")
right = df_all.loc[df_all['predict'] == df_all['isSignal']]
wrong = df_all.loc[df_all['predict'] != df_all['isSignal']]

true_positive = right.loc[right['predict'] == 1]
false_positive = wrong.loc[wrong['predict'] == 1]
false_negative = wrong.loc[wrong['predict'] == 0]

print("We had %d elements in our recordset." % len(df_all))
print("We classified correctly %d events." % len(right))
print("We classified wrongly %d events." % len(wrong))
print("We had %d false positive and %d false negative." % (len(false_positive), len(false_negative)))

print("")

print("Our precision has been %1.2f." % (len(true_positive)/(len(true_positive) + len(false_positive))))
print("Our recall has been %1.2f." % (len(true_positive)/(len(true_positive) + len(false_negative))))<jupyter_output>We had 20738 elements in our recordset.
We classified correctly 16199 events.
We classified wrongly 4539 events.
We had 4448 false positive and 91 false negative.

Our precision has been 0.78.
Our recall has been 0.99.<jupyter_text>Proviamo a fare una rete con una topologia differente, con 2 percettroni di uscita:<jupyter_code>model2 = Sequential()

model2.add(Dense(2, input_dim=2))
model2.add(ReLU())
model2.add(Dense(units=2))
model2.add(ReLU())
model2.add(Dense(units=2, activation='softmax'))


model2.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

# print the model summary
model2.summary()
# early stopping callback
from keras.callbacks import EarlyStopping
early_stopping = EarlyStopping(monitor='val_loss', patience=10)

history = model2.fit(X_train_val,
                    y_train,
                    epochs=1000, 
                    verbose=1, # switch to 0 for less verbosity 
                    callbacks=[early_stopping], 
                    validation_data=(X_test_val, y_test))
import matplotlib.pyplot as plt

# plot loss vs epoch
plt.figure(figsize=(12, 4))
plt.plot(history.history['loss'], label='loss')
plt.plot(history.history['val_loss'], label='val_loss')
plt.legend(loc="upper right")
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

# plot accuracy vs epoch
plt.figure(figsize=(12, 4))
plt.plot(history.history['accuracy'], label='accuracy')
plt.plot(history.history['val_accuracy'], label='val_accuracy')
plt.legend(loc="upper left")
plt.xlabel('epoch')
plt.ylabel('acc')
plt.show()
X_val = scaler.transform(X)
df_all['predict'] = 1 - model2.predict(X_val)

df_all['predict'] = np.around(df_all['predict']).astype(np.int64)
df_all['isSignal'] = np.around(df_all['isSignal']).astype(np.int64)

df_all
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(df_all['isSignal'].array, df_all['predict'].array)
classes = ['No', 'Yes']

fig, ax = plt.subplots()
im = ax.imshow(cm, cmap=plt.cm.Blues)

ax.figure.colorbar(im, ax=ax)
ax.set(xticks=np.arange(cm.shape[1]),
       yticks=np.arange(cm.shape[0]),
       xticklabels=classes,
       yticklabels=classes,
       ylabel='True label',
       xlabel='Predicted label')

for i in range(cm.shape[0]):
    for j in range(cm.shape[1]):
        ax.text(j, i, format(cm[i, j], 'd'),
                ha="center", va="center",
                color="white" if cm[i, j] > cm.max() / 2. else "black")
right = df_all.loc[df_all['predict'] == df_all['isSignal']]
wrong = df_all.loc[df_all['predict'] != df_all['isSignal']]

true_positive = right.loc[right['predict'] == 1]
false_positive = wrong.loc[wrong['predict'] == 1]
false_negative = wrong.loc[wrong['predict'] == 0]

print("We had %d elements in our recordset." % len(df_all))
print("We classified correctly %d events." % len(right))
print("We classified wrongly %d events." % len(wrong))
print("We had %d false positive and %d false negative." % (len(false_positive), len(false_negative)))

print("")

print("Our precision has been %1.2f." % (len(true_positive)/(len(true_positive) + len(false_positive))))
print("Our recall has been %1.2f." % (len(true_positive)/(len(true_positive) + len(false_negative))))<jupyter_output>We had 20738 elements in our recordset.
We classified correctly 20420 events.
We classified wrongly 318 events.
We had 172 false positive and 146 false negative.

Our precision has been 0.99.
Our recall has been 0.99.
{'fraction_non_alphanumeric': 0.16148761961132485, 'fraction_numerical': 0.040445891289336094, 'mean_word_length': 5.0059241706161135, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 42, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '71158', 'license': 'Apache-2.0', 'n_tokens_mistral': 3967, 'n_tokens_neox': 3567, 'n_words': 828, 'path': 'Lezioni/Lezione 7.B - Soluzioni.ipynb', 'repo_name': 'biancini/DataScience-HEP', 'size': '10137'}