The concept of falsifiability of a scientific theory is discussed. First I define what is meant by falsifiability and then discuss the main criticisms of falsifiability and how the science developments react with the sharp edge of the restriction condition of what is defined as science. The last discussion is focusing on the limits that modern development in physics put on falsifiability.

In the context of the language study, falsifiability is the ability to make false, or incorrect statements about something., the linguistic root of the term is meaningful, in all contexts, it explains what could be able to determine if it could be wrong or not. And the philosophical meaning of the term uses the exact meaning of the word. But before we go looking for a precise definition of what is falsifiability, we discuss the situation before Karl Popper’s proposition about falsifiability as a criterion of science.

The verification as a criterion of science was dominated over a long period. According to the Philosophical Encyclopedia definition, it is a principle holding that a statement is meaningful only if it is either empirically verifiable or else tautological (i.e., such that its truth arises entirely from the meanings of its terms). Thus, the principle discards as meaningless the metaphysical statements of traditional philosophy as well as other kinds of statements—such as ethical, aesthetic, or religious principles—asserted as true but neither tautological nor known from experience. Such statements may have meaning in the sense of being able to influence feelings, beliefs, or conduct but not in the sense of being true or false and hence of imparting knowledge. According to the principle, then, a non-tautological statement has meaning only if some set of observable conditions is relevant to determining its truth or falsity; so stated, it reflects the view that the meaning of a statement is the set of conditions under which it would be true. **[1]**

Falsifiability in the philosophy of science is a standard of evaluation of scientific theories, according to which a theory belongs to science or not. This criterion is that the theory is scientific only if there is a possibility in principle to prove that it is false. Karl Popper proposes this criterion as a solution to the demarcation problem which is the problem of specifying what is science from pseudoscience. Karl Popper describes demarcation to be the key to most of the fundamental problems in the philosophy of science”** [2]**. He also defines falsifiability criterion in the following manner, statements or systems of statements to be ranked as scientific, must be capable of conflicting with possible, or conceivable observations” **[3]**. Popper’s motivation to propose this criterion was based on his criticism of confirmation and his opinion that a scientific theory cannot be confirmed because there still observations that are inconsistent with the experimental prediction of the theory. However, Popper’s idea was not about the number of experimental observations that could verify the theory, it is about that the theory needs to have an observation that can prove it's inconsistently with empirical facts.

Popper argues that verification and confirmation played no role in formulating a satisfactory criterion of demarcation. Instead, Popper proposes that scientific theories are characterized by being bold in two related ways. First, scientific theories regularly disagree with accepted views of the world based on common sense or previous theoretical commitments. To an uneducated observer, for example, it may seem obvious that Earth is stationary, while the sun moves rapidly around it. However, Copernicus posited that Earth revolved around the sun. Similarly, it does not seem as though a tree and a human share a common ancestor, but this is what Darwin’s theory of evolution by natural selection claims. As Popper notes, however, this sort of boldness is not unique to scientific theories, since most mythological and metaphysical theories also make bold, counterintuitive claims about the nature of reality. For example, the accounts of world creation provided by various religions would count as bold in this sense, but this does not mean that they thereby count as scientific theories.

Regarding the discussions of limits of falsifiability, Let discuss how modern developments in physics which lead to the paradigm of science. We will discuss several factors when taken into account weaken the principle of falsifiability and put certain limits upon its general validity. The first concern is that we can not from the logical perspective conclude from a mismatch between theory and experiment that the theory is necessarily false. The error may be due to any number of other causes, known or unknown. For example, the mismatch may be due to experimental error as in the Faster than light neutrino anomaly **[4]**, mistakes in calculating the predictions from the hypothesis, or auxiliary assumptions that have been made as in the irregularities in the orbit of Uranus because the existence of Neptune was not taken into account. In addition, experimental facts themselves are theory-laden. So, it cannot test a theory against experimental facts, independent of a theory. These assumptions and conditions of testing a theory can be so numerous that falsifying a theory, in a strictly logical sense, is often practically impossible.

The second concern with falsifiability is that, if it is strictly applied, it excludes from science certain hypotheses that are valuable to investigate, such as the hypothesis of proton decay in SU(5) symmetry theories. Although it can experimentally confirm the hypothesis of proton decay, it is not falsifiable because, no matter how long experiments fail to observe proton decay **[5]**, there will always remain the possibility that it still could decay, and it is only possible to falsify specific bounds on its half-life (some estimates this half-life with a value bigger than universe age). Even though the hypothesis of proton decay is not falsifiable, it is valuable to investigate since an observation of proton decay would falsify the Standard Model of modern physics which is the best-known physics at this stage. Thus, it is not good scientific practice to make a policy of uniformly dismissing any claim as an unscientific claim simply because it is not, taken alone, a falsifiable hypothesis.

The last limit that modern physics put on falsifiability is that it excludes older theories that are, strictly speaking, false but still useful within limited domains where they remain valid approximations. Newton’s theory of gravity, for example, is strictly speaking falsely because it predicts motions that are not precisely correct as they neglect relativistic effects. Nonetheless, Newton’s theory is still considered scientific because its predictions are within the bounds of experimental error in most practical circumstances. So, even if a theory is, strictly speaking, false, that does not imply that it is unscientific or no longer approximately valid. Other examples of this problem are all the physics laws that in principle have their limitations and most of them are not valid in all contexts. Even the standard model of modern physics predicts that neutrino is a massless particle, but the experimental observation verifies that it has a mass. This does not mean that it is wrong in all context as its all other predictions are experimentally confirmed as true. So a general theory that includes the standard model is required, and it is what the scientific community is trying to find. They ignore the criterion of falsifiability not because they abounded it but because it is not effective enough to deal with the modern development and current situation of physics.

**[1]** *Britannica, T. E. (2016, April 26). Verifiability principle. Retrieved April 19, 2018, from https://www.britannica.com/topic/verifiability-principle*** ****[2]** *Popper, Karl, 1962. Conjectures and refutations. The growth of scientific knowledge, New York: Basic Books, page 42.*** ****[3]** *Popper, Karl, 1962. Conjectures and refutations. The growth of scientific knowledge, New York: Basic Books, page 39.*** [4] ***Brumfiel, G. (2012). Neutrinos not faster than light. Nature. doi:10.1038/nature.2012.10249* **[5] ***Senjanovic, Goran AIP Conf. Proc. 1200 (2010) 131-141 arXiv:0912.5375 [hep-ph]*

During my first year PhD at UC, I get the chance to take statistical mechanics class from a condensed matter physicist. It was a new experience when he focused too much on different side that I did not explore before. The final project in this class was about using Monte-Carlo method to simulate the Ising model. Ising model is a model of a system that undergoes a phase transition. There are many reasons why this model is interesting when it is not representing any actual physical systems.

- It can be solved exactly, We can calculate the thermodynamical quantities and interpret them. In another can calculate the partition function and put it in an exact form.
- Ising model exhibits symmetry breaking in low-temperature phase.
- The Ising model is simple, yet it can be applied to many physical systems. This gives us a feature about
**universality,**a feature that tells us that in such case the same theory applies to all sorts of different phase transitions.

We can think of Ising model as a mathematical model where everything consists of small squares inside a bigger one. It is usually called lattices where we then have a big lattice of sites (small boxes) where each site can be in one of two states. Those states as we will see will refer to the spin state of the electron inside this site. Each site will be labeled by index \( i\). The Hamiltonian for the Ising model can be written as

\[ \mathcal{H}=-J \sum_{\langle i j\rangle} S_{i} S_{j}\]

- Spin \(S_{i}\) has values \(+1\) or \(-1\)
- \({\langle i j\rangle}\) implying that we are interested in nearest-neighbor interaction only.
- \(J\) > 0 as we are assuming that strength is positive.

There are many systems that can be represented using this model like "lattice gas" with each of the sites is the possible location of a particle; means that site is empty and means that site is occupied by a particle.

This system will undergo a 2nd order phase transition at some temperature \(T = T_c\) which is called critical temperature. For cases when \(T < T_c\), the system magnetizes, and the state is called the ferromagnetic state which is an ordered state. For cases when \(T > T_c\), the system is disordered or in a paramagnetic state. We can define the order parameter for this system to be the average magnetization \(m\).

\[m=\frac{\langle S\rangle}{N}\]

This parameter is used to distinguish between the two phases that this system can have. It is zero when we are in disordered (paramagnetic) state and takes a non-zero value in ordered (ferromagnetic) state.

In this section, I'm going through the details of implementing the Monte-Carlo (MC) method for our Ising model. I apply the MC methods using Metropolis Algorithm to Ising model and extract physical parameters (Energy, Specific heat and Magnetization).

Lattice is a periodical structure of points that align one by one. 2D lattice can be plotted as:

```
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* * * * * * * *
```

The points in lattice are called lattice points, nearest lattice points of point ^ are those lattice points denoted by (*) shown in the graph below:

```
* * *(*)* * * *
* *(*)^(*)* * *
* * *(*)* * * *
* * * * * * * *
```

Each lattice point is denoted by a number i in the Hamiltonian.

The expression for the Energy of the total system is

\[H = - J \sum_{ i = 0 }^{ N-1 } \sum_{ j = 0 }^{ N-1 } (s_{i,j}s_{i,j+1}+s_{i,j}s_{i+1,j})\]

```
* * * * * * * *
* * * * * * * *
* * * * * * * * <-the i-th lattice point
* * * * * * * *
* * * * * * * *
```

Periodical structure means that lattice point at(1,1) is the same as that at(1,9) if the lattice is 5 x 8. For example (1,1)<=>(6,1), (2,3)<=>(2,11). A 2D lattice can be any \(N_x\) by \(N_y\). The location \((x,y)\) here is another denotion of lattice point that is fundamentally same as i-th lattice point denotation above.

```
* * * * * * * * 4
* * * * * * * * 3
* * * * * * * * 2
* * * * * * * * 1
1 2 3 4 5 6 7 8
```

- Prepare some initial configurations of N spins.
- Flip spin of a lattice site chosen randomly
- Calculate the change in energy due to that
- If this change is negative, accept such move. If change is positive, accept it with probability exp^{-dE/kT}
- Repeat 2-4.
- Calculate Other parameters and plot them

```
#----------------------------------------------------------------------
## Import needed python libraries
#----------------------------------------------------------------------
import matplotlib.pyplot as plt
from numba import jit # wonderful optimization compiler.
import numpy as np # we can't work in python without that in physics (maybe we can if we are not lazy enough)
import random # we are doing MC simulation after all!!
import time # for time estimation
from tqdm import tqdm # fancy progress bars for loops , use this line if working with .py script
#from tqdm.notebook import tqdm # use this if working with jupyter notebook to avoid printing a new line for each iteration
from rich.progress import track # we can use rich library.change "tqdm" later to "track"
```

```
# Define parameters
B = 0; # Magnetic field strength
L = 50; # Lattice size (width)
s = np.random.choice([1,-1],size=(L,L)) # Begin with random spin sites with values (+1 or -1) for up or down spins.
n= 1000 * L**2 # number of MC sweeps
Temperature = np.arange(1.6,3.25,0.01) # Initlaize temperature range, takes form np.arange(start,stop,step)
```

```
# Define functions to compute energy and magnetization
'''
Energy of the lattice calculations.
The energy here is simply the sum of interactions between spins divided by the total number of spins
'''
@jit(nopython=True, cache=True) # wonderful jit optimization compiler in its high performance mode
def calcE(s):
E = 0
for i in range(L):
for j in range(L):
E += -dE(s,i,j)/2
return E/L**2
'''
Calculate the Magnetization of a given configuration
Magnetization is the sum of all spins divided by the total number of spins
'''
@jit(nopython=True, cache=True) # wonderful jit optimization compiler in its high performance mode
def calcM(s):
m = np.abs(s.sum())
return m/L**2
```

```
# Calculate interaction energy between spins. Assume periodic boundaries
# Interaction energy will be the difference in energy due to flipping spin i,j
# (Example: 2*spin_value*neighboring_spins)
@jit(nopython=True, cache=True) # wonderful jit optimization compiler in its high performance mode
def dE(s,i,j): # change in energy function
#top
if i == 0:
t = s[L-1,j] # periodic boundary (top)
else:
t = s[i-1,j]
#bottom
if i == L-1:
b = s[0,j] # periodic boundary (bottom)
else:
b = s[i+1,j]
#left
if j == 0:
l = s[i,L-1] # periodic boundary (left)
else:
l = s[i,j-1]
#right
if j == L-1:
r = s[i,0] # periodic boundary (right)
else:
r = s[i,j+1]
return 2*s[i,j]*(t+b+r+l) # difference in energy is i,j is flipped
```

```
# Monte-carlo sweep implementation
@jit(nopython=True, cache=True) # wonderful jit optimization compiler in its high performance mode
def mc(s,Temp,n):
for m in range(n):
i = random.randrange(L) # choose random row
j = random.randrange(L) # choose random column
ediff = dE(s,i,j)
if ediff <= 0: # if the change in energy is negative
s[i,j] = -s[i,j] # accept move and flip spin
elif random.random() < np.exp(-ediff/Temp): # if not accept it with probability exp^{-dU/kT}
s[i,j] = -s[i,j]
return s
```

```
# Compute physical quantities
@jit(nopython=True, cache=True) # wonderful jit optimization compiler in its high performance mode
def physics(s,T,n):
En = 0
En_sq = 0
Mg = 0
Mg_sq = 0
for p in range(n):
s = mc(s,T,1)
E = calcE(s)
M = calcM(s)
En += E
Mg += M
En_sq += E*E
Mg_sq += M*M
En_avg = En/n
mag = Mg/n
CV = (En_sq/n-(En/n)**2)/(T**2)
return En_avg, mag, CV
```

```
# Inititalize magnetization, average energy and heat capacity
mag = np.zeros(len(Temperature))
En_avg = np.zeros(len(Temperature))
CV = np.zeros(len(Temperature))
start = time.time()
```

```
# Simulate at particular temperatures (T) and compute physical quantities (Energy, heat capacity and magnetization)
for ind, T in enumerate(track(Temperature)):
# Sweeps spins
s = mc(s,T,n)
# Compute physical quanitites with 1000 sweeps per spin at temperature T
En_avg[ind], mag[ind], CV[ind] = physics(s,T,n)
end = time.time()
print("Time it took in seconds is = %s" % (end - start))
time = (end - start)/60
print('It took ' + str(time) + ' minutes to execute the code')
```

```
#----------------------------------------------------------------------
# Plotting area
#----------------------------------------------------------------------
f = plt.figure(figsize=(18, 10)); # plot the calculated values
sp = f.add_subplot(2, 2, 1 );
plt.plot(Temperature, En_avg, marker='.', color='IndianRed')
plt.xlabel("Temperature (T)", fontsize=20);
plt.ylabel("Energy ", fontsize=20); plt.axis('tight');
sp = f.add_subplot(2, 2, 2 );
plt.plot(Temperature, abs(mag), marker='.', color='RoyalBlue')
plt.xlabel("Temperature (T)", fontsize=20);
plt.ylabel("Magnetization ", fontsize=20); plt.axis('tight');
sp = f.add_subplot(2, 2, 3 );
plt.plot(Temperature, CV, marker='.', color='IndianRed')
plt.xlabel("Temperature (T)", fontsize=20);
plt.ylabel("Specific Heat ", fontsize=20); plt.axis('tight');
plt.subplots_adjust(0.12, 0.11, 0.90, 0.81, 0.26, 0.56)
plt.suptitle("Simulation of 2D Ising Model by Metropolis Algorithm\n" + "Lattice Dimension:" + str(L) + "X" + str(
L) + "\n" + "External Magnetic Field(B)=" + str(B) + "\n" + "Metropolis Step=" + str(n))
plt.show() # function to show the plots
```

These are plots of the physical quantities for different MC steps.

You can run the Jupyter Notebook provided on Colab directly, or you can download from my project GitHub repository and run locally. Also, there is python script that you can run. I'm using Numba cache so that it produces cache folder (specific to machine CPU and configuration) so that you will need to produce yours by running it for one time and subsequent runs will be about twice faster.

To run the script

- clone the repository

`git clone https://github.com/MohamedElashri/IsingModel`

2. run the script

`python3 IsingModel.py`

I spent many nights working on this work, most of time I needed to optimize my code, I even tried to move to Matlab (last time I used it was like 5 years ago). But I learned a nice thing from my desire to optimize code speed. It is the usage of Numba’s JIT compiler. Read more about that here link. I also instead of using multiple nested loops I dragged all these into just one. Imagine running 50x50 lattice simulation in my older codes for hours (one took 6 hours) vs 15 minutes for the current script. (On my Mac m1 Machine). Also, I made the code available on colab and can be accessed here (without many comments) link.

]]>In this blog post, I'm going to walk through about applying machine learning algorithms in particle physics. There are many available datasets ready for ML but one of a particular interest is the MiniBooNE dataset available on UCI machine learning repository. This dataset is used for a published paper from the experiment collaboration which is very interesting to read although it is somehow old. Particle Identification was part of the early success stories for machine learning and deep learning so it was applied since early 2000's.

- The dataset has been taken from UCI machine learning repository
- It has been taken from the MiniBooNE experiment conducted in the fermilab.
- A stream of muon neutrinos are fired and the detector measures the precense of electron neutrinos(signal) among the muon neutrinos(noise).
- There are 50 features in the dataset related to every detection made , however no information is given about the features.
- There are no missing values.
- The first line in the file MiniBooNE_PID.txt contains 2 space seperated values , the signal events come first, followed by the background events
- This is a binary classification problem where we want to tell wether a given signal is a electron neutrino or not.

we can download the dataset directly in our python/jupyter workspace using:

```
wget -O data.txt -nc --no-check-certificate https://archive.ics.uci.edu/ml/machine-learning-databases/00199/MiniBooNE_PID.txt
```

we will need to do some data processing to make the data ready for more steps. we are going to do the following:

- The data is stored in data.txt which was downloaded from the above link.
- We use the pandas library to read the data and skip the first row as it contains the number of positive and negative labels
- Then we create a numpy array of 1's(electron neutrino) and 0's(muon neutrino) which acts as our labels for the classification problem.
- We then convert the input dataframe into a numpy array for the analysis.
- After having a look at the data we see that there are many features having large values. This makes the Machine Learning algorithms difficult to converge to a result. Therefore, the solution is to scale down the data.
- Here, we just want the range to change, not the mean, or the variance so that the data still caries the information it did before scaling. Hence a good scaler to use is the minmax scaler.
- We then use the train test split to split the data into training and test data sets with a default of 75% training data and 25% test data.

Lets code this

We need to import the needed packages

```
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import GridSearchCV
from sklearn import metrics
import matplotlib.pyplot as plt
```

define data and read it into pandas dataframe

`df=pd.read_csv('data.txt',sep=' ',header=None,skiprows=1,skipinitialspace=True)`

We explore data features

`df.head()`

we see this output

Now we need to scale the data

```
file=open('data.txt')
y=file.readline()
file.close()
numlabels=[int(s) for s in y.split()]
ylabels=numlabels[0]*[1] + numlabels[1]*[0]
Y=np.array(ylabels)
X=df.to_numpy()
scaler=MinMaxScaler()
scaler.fit(X)
X_scaled=scaler.transform(X)
```

Then split the dataset into training and test sets

`X_train,X_test,y_train,y_test=train_test_split(X_scaled,Y,random_state=0)`

we are going to apply different ML algorithms on our data and will need to determine a rubric to evaluate our models. We define a function for model evaluation based on the confusion matrix. The confusion matrix is used to quantify how many of the predicted values were correct and incorrect.

**Definitions**

**Accuracy**: The number of true predictions(true 0's and true 1's) divided by the total number of predictions made**Precicion**: The number of true 1's divided by the total number of 1's predicted.(Basically telling us that how well have we predicted the 1's) precision=1 if no 1's are predicted as 0 (precision=TP/(TP+FP))**Recall**: The number of true 1's divided by the actual 1's.(the fraction of correctly classified 1's) . recall=1 if no 1s are predicted as 0.(recall=TP/(TP+FN))**ROC**: a graph where false positive rate is plotted on the X-axis and true positive rate is plotted in the Y axis. The area under the ROC curve is a good measure of how well the algorothm has performed. A score close to 1 is a good auc(area under the curve) score.

```
def evaluate(y_test,y_pred,y_pred_proba):
cnf_matrix=metrics.confusion_matrix(y_test,y_pred)
print('The confusion matrix for the given model is: ')
print(cnf_matrix)
print('accuracy : ',metrics.accuracy_score(y_test,y_pred))
print('precision : ',metrics.precision_score(y_test,y_pred))
print('recall : ',metrics.recall_score(y_test,y_pred))
fpr, tpr, _ = metrics.roc_curve(y_test, y_pred_proba)
auc = metrics.roc_auc_score(y_test, y_pred_proba)
plt.figure()
plt.plot(fpr,tpr,label='Area under the curve= '+str(auc))
plt.legend(loc=4)
plt.title('ROC curve')
plt.xlabel('False positive rate')
plt.ylabel('True Positive rate')
```

In this analysis we will try different machine learning algorithm and seek the best model among them. We will use the following models

- Logistic regression
- K-nearest Neigbhors
- Decision trees
- SVM (Support Vector Machines)
- Random Forest

Logistic regression uses the sigmoid function to estimate the probability of an instance being classified as 1. The C value controls large values for weights that may lead to over fitting in the data

```
from sklearn.linear_model import LogisticRegression
# define the model
lr=LogisticRegression(random_state=0,max_iter=5000)
C_range={'C':[100]}
clf=GridSearchCV(lr,C_range).fit(X_train,y_train)
# print model scores
print('The score for this model is: ',clf.score(X_test,y_test))
print('the best value of parameter C is: ',clf.best_params_)
y_pred=clf.predict(X_test)
y_pred_proba=clf.predict_proba(X_test)[::,1]
# evaluate the model
evaluate(y_test,y_pred,y_pred_proba)
```

The output will be the following

The score for this model is: 0.8730778693566245

the best value of parameter C is: {'C': 100}

The confusion matrix for the given model is: [[22184 1268] [ 2859 6205]] accuracy : 0.8730778693566245

precision : 0.8303224943128596

recall : 0.684576345984113

The K-nearest neighbors model does not actually train a model based on the data but rather stores all the training data given to it and then calculates the distance of each point from every other point.When test data is given, it classifies it as a 1 or 0 based on votes based on the chosen k(number of nearest neighbors). It is unsupervised learning algorithm

```
from sklearn.neighbors import KNeighborsClassifier
# define the model
knn=KNeighborsClassifier()
parameters_knn={'n_neighbors':[1,5,10,14]}
clf=GridSearchCV(knn,parameters_knn).fit(X_train,y_train)
# print model scores
print('The score for this model is: ',clf.score(X_test,y_test))
print('the best value of parameters is: ',clf.best_params_)
y_pred=clf.predict(X_test)
y_pred_proba=clf.predict_proba(X_test)[::,1]
# evaluate the model
evaluate(y_test,y_pred,y_pred_proba)
```

The output will be the following

The score for this model is: 0.8901463894697995

the best value of parameters is: {'n_neighbors': 14}

The confusion matrix for the given model is: [[21821 1631] [ 1941 7123]]

accuracy : 0.8901463894697995

precision : 0.8136851724925748

recall : 0.785856134157105

A Binary Decision Tree is a structure based on a sequential decision process. Starting from the root, a feature is evaluated and one of the two branches is selected. This procedure is repeated until a final leaf is reached, which normally represents the classification target we are looking for. The model can over fit if no limit is specified on the depth the tree can go to.

```
from sklearn import tree
# define the model
dt=tree.DecisionTreeClassifier()
parameters_dt={'max_depth':[5,10,15]}
clf=GridSearchCV(dt,parameters_dt).fit(X_train,y_train)
# print model scores
print('The score for this model is: ',clf.score(X_test,y_test))
print('the best value of parameters is: ',clf.best_params_)
y_pred=clf.predict(X_test)
y_pred_proba=clf.predict_proba(X_test)[::,1]
# evaluate the model
evaluate(y_test,y_pred,y_pred_proba)
```

The output will be the following

The score for this model is: 0.908721860007381

the best value of parameters is: {'max_depth': 10}

The confusion matrix for the given model is: [[21899 1553] [ 1415 7649]]

accuracy : 0.908721860007381

precision : 0.8312323407954793

recall : 0.8438879082082965

random forest is a classification algorithm consisting of many decisions trees. It uses bagging and feature randomness when building each individual tree to try to create an uncorrelated forest of trees whose prediction by committee is more accurate than that of any individual tree

```
from sklearn.ensemble import RandomForestClassifier
# define the model
rf=RandomForestClassifier(bootstrap=True)
parameters_rf={'n_estimators':[10,50,100],'max_depth':[5,10],'max_samples':[30000,40000]}
clf=GridSearchCV(rf,parameters_rf).fit(X_train,y_train)
# print model scores
print('The score for this model is: ',clf.score(X_test,y_test))
print('the best value of parameters is: ',clf.best_params_)
y_pred=clf.predict(X_test)
y_pred_proba=clf.predict_proba(X_test)[::,1]
# evaluate the model
evaluate(y_test,y_pred,y_pred_proba)
```

The output will be the following

The score for this model is: 0.925544347398204

the best value of parameters is: {'max_depth': 10, 'max_samples': 40000, 'n_estimators': 100}

The confusion matrix for the given model is: [[22346 1106] [ 1315 7749]]

accuracy : 0.925544347398204

precision : 0.8750988142292491

recall : 0.8549205648720212

In our Analysis we find "*Random forest*" is the best algorithm with the highest ROC value

Two years ago, I started my Master's degree at the University of Minnesota, I had experience defending my undergraduate thesis a couple of months before that. I expected something special for my defense for a graduate degree. Things went to more than I could even imagine. During my two years after moving to the US and trying to adapt to my new life, After restless days and nights of trying to maintain a good standing postilion in NOvA Collaboration. I spent most of my time learning about every aspect of my research, I was looking to magnetic monopole which is an exotic search and usually not appreciated by most of the collaboration members. I learned a lot of stuff, faced a lot of problems where in some times no one could help me. I wanted to make my defense day even more memorable. But I never expected that it would turn out like this: it was held in the middle of a pandemic that will forever trigger memories of writing and defending my thesis. Within the months prior to the pandemic, I imagined my defense to be in the fanciest room on campus and I would provide my audience with a chocolate fountain. I was thinking about inviting all of my Muslim community in our small city. However, those ideas quickly vanished as the COVID-19 pandemic forced my defense to be held remotely.

The defense took place through zoom which became the standard way of communication for most people. We were using it always at NOvA collaboration and I hated the way it works even before covid19. Instead of being in a room filled with curious eyes and chocolate-covered mouths, I was in a video meeting where I felt as if I was just talking to my PowerPoint because the meeting screen, I wasn't even able to share my video as it affects the bandwidth. My camera was also off until the end where I gave the acknowledgments and answered questions. I did this to narrow the connection bandwidth and to secretly refer to notes to each of the slides on my iPad. Since I wasn’t able to view my audience, the actual presentation felt more like a practice run and it wasn’t until the very last slide, where I gave my acknowledgments. to make things worse, my PowerPoint froze a couple of times. Since this was actually a real talk and not a practice, the multiple computer glitches made me feel like I was further being initiated into the world of professional physics research.

At the end of the talk, the smiles from friends and visual satisfactory nods from my MS committee were lost as most people just sent “clap“ emojis and other appraisal messages through the chat window. My advisor then asked if there were any questions, the 15–30 seconds of silence felt like an eternity as I patiently waited for someone to ask anything they wanted about my research. I was furious until one of my colleagues raised his hand and they asked a question. The back and forth felt similar to virtual teaching (due to the pandemic) Labs that I was a Teaching Assistant (TA) for during the past term and the summer quick semester trying to answer a question as completely as possible while also trying to figure out who was asking the question. Now, while I didn’t get the room setup that I imagined and lost the visual interaction with my audience, the virtual setup did allow me to invite my friends back home from outside of the US who otherwise would have not been able to attend.

It was a difficult experience and wasn't what I always had in my mind for my defense day. I felt after everything is done and everyone left zoom meeting that nothing changed. It is still that normal day that I will keep myself inside my room and be carful not to go outside while the peak of the pandemic is there. I will move to start my PhD in a couple of days and I will go on another journey which will be longer this time and will start in the worst time possible.

One of the most beautiful ideas about excluding the possibility of neutrinos to be the dark matter candidates is through a simple answer to a simple question. What is the number of particles that could be in a galaxy?. In 1979 there was a paper published trying to answer this question (1). It is called Tremaine-Gunn bound, which put an also constrain for the dark matter candidates.

We know that the galaxy is a pretty big object, and particles are microscopic objects, so the answer is definitely “a lot.” But in physics, there are two types of particles, fermions (the matter particles we composed of) and bosons. For fermions, however, the answer isn’t “infinity.” And that turns out to be very interesting. Fermions are spin-1/2 particles, and they have the property that two fermions cannot exist in the same quantum state. This is the Pauli Exclusion Principle.

Quantum states include “position,” so what this means is that, if you start trying to pile fermions on top of each other, they will have to sit “next” to each other. This is why all the fields we think of as “matter” are fermionic (electrons, protons, neutrons). So let’s imagine that dark matter is some unknown fermion. Then we can start piling up dark matter inside a galaxy. Each particle you add to the galaxy makes it’s mass a bit larger, but also takes up a slot in the position and momentum quantum states. Eventually, you’ll have added so many fermions that the only quantum states that remain open would require a fermion to be so far away from the galactic center and moving so fast that it would no longer be gravitationally bound to the galaxy.

So there is a maximum number of dark matter fermions you can add to a galaxy. If the dark matter is too light, then this number of fermions would not possibly accommodate the total dark matter mass of the galaxy. Looking at dwarf galaxies, you can use this technique to place the simplest version of the Tremaine-Gunn bound: if dark matter is a fermion, it needs to be heavier than about one keV. You can sharpen this argument at bit using phase-space mixing and get the limit up to ~ three keV.

Interestingly, despite neutrinos being otherwise ideal as a dark matter candidate, this limit told us they could not be dark matter. We know that neutrinos are much lighter than 1-3 keV. So you literally cannot cram enough neutrinos into a galaxy for them to be the dark matter. Amusingly, this Pauli Exclusion Limit for fermions is also what supports a white dwarf or neutron star from gravitational collapse. If the star got smaller, there wouldn’t be enough room for the electrons (dwarfs) or neutrons (neutron stars) without doubling up on quantum states. If dark matter is a boson, you can’t use the Tremaine-Gunn bound, since bosons are okay with all sitting in the same quantum state. So in principle, you can fit an infinite number inside a galaxy. You can use another property of quantum fields to constrain bosonic dark matter, though. If the particle is too light, the quantum wavefunction is so dispersed it cannot be localized inside the galaxy.

This puts a lower bound of ~10^-22 eV on bosonic dark matter. Rather less than the bound for fermionic dark matter. But at least this is even a “thing.” Of course, there are other reasons to eliminate neutrinos as a dark matter candidate, but yet we know more about what couldn’t be a dark matter, not what is the dark matter. 😏

[1] (S. Tremaine and J. E. Gunn, Phys. Rev. Lett. 42, 407 (1979).)

]]>