├── Smiley.png ├── Week3 ├── Smiley.png ├── Week3_ImageReproduce.py ├── Week3_SimpleKeras.py └── Week3_MNIST_TF.py ├── Week9 ├── dcgan.gif └── Week9_KDE.py ├── README.md ├── requirements.txt ├── Week5 ├── .ipynb_checkpoints │ └── Week5_tSNE-checkpoint.ipynb ├── Week5_PCA.py └── Week5_tSNE.py ├── Week8 ├── Week8_Ising.py └── Week8_BoltzmannMachine.py ├── Week4 ├── Week4_MNIST_TF_Live.py ├── Week4_ConvolutionalNeuralNetwork.py └── Week4_Autoencoder.py ├── Week6 ├── Week6_pandas.py ├── Week6_TF_IMDB.py ├── Week6_Prediction.py └── Week6_LSTM.py ├── Week7 ├── Week7_MazePolicy.py ├── Week7_PolicyGradient.py └── Week7_RL.py ├── Week2 ├── Week2_ChatGPT_NN.py └── Week2_BackPropagation.py └── Week1 └── Week1_CurveFitting.py /Smiley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nichol77/mlForPhysicists/HEAD/Smiley.png -------------------------------------------------------------------------------- /Week3/Smiley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nichol77/mlForPhysicists/HEAD/Week3/Smiley.png -------------------------------------------------------------------------------- /Week9/dcgan.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nichol77/mlForPhysicists/HEAD/Week9/dcgan.gif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mlForPhysicists 2 | Machine Learning For Physicists 3 | 4 | These notebooks have been put together as part of a "Machine Learning for Physicists" course for UCL Physics and Astronomy students that will run for the first time in the Autumn term 2020. 5 | 6 | Some of the examples in this course were heavily inspired by the https://machine-learning-for-physicists.org course that has been run a few times by Florian Marquardt. 7 | 8 | All of the notebooks are hereby provided under the terms of the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license: 9 | 10 | https://creativecommons.org/licenses/by-sa/4.0/ -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | appnope==0.1.0 2 | astroid==2.2.5 3 | backcall==0.2.0 4 | decorator==4.4.2 5 | ipykernel==5.3.0 6 | ipython==7.15.0 7 | ipython-genutils==0.2.0 8 | isort==4.3.17 9 | jedi==0.17.1 10 | jupyter-client==6.1.3 11 | jupyter-core==4.6.3 12 | lazy-object-proxy==1.3.1 13 | matplotlib==3.1.3 14 | mccabe==0.6.1 15 | numpy==1.17.4 16 | parso==0.7.0 17 | pexpect==4.8.0 18 | pickleshare==0.7.5 19 | prompt-toolkit==3.0.5 20 | ptyprocess==0.6.0 21 | Pygments==2.6.1 22 | pylint==2.3.1 23 | python-dateutil==2.8.1 24 | pyzmq==19.0.1 25 | six==1.12.0 26 | tornado==6.0.4 27 | traitlets==4.3.3 28 | typed-ast==1.3.1 29 | wcwidth==0.2.4 30 | wrapt==1.11.1 31 | -------------------------------------------------------------------------------- /Week5/.ipynb_checkpoints/Week5_tSNE-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [] 9 | } 10 | ], 11 | "metadata": { 12 | "kernelspec": { 13 | "display_name": "Python 3", 14 | "language": "python", 15 | "name": "python3" 16 | }, 17 | "language_info": { 18 | "codemirror_mode": { 19 | "name": "ipython", 20 | "version": 3 21 | }, 22 | "file_extension": ".py", 23 | "mimetype": "text/x-python", 24 | "name": "python", 25 | "nbconvert_exporter": "python", 26 | "pygments_lexer": "ipython3", 27 | "version": "3.7.6" 28 | } 29 | }, 30 | "nbformat": 4, 31 | "nbformat_minor": 4 32 | } 33 | -------------------------------------------------------------------------------- /Week9/Week9_KDE.py: -------------------------------------------------------------------------------- 1 | # --- 2 | # jupyter: 3 | # jupytext: 4 | # text_representation: 5 | # extension: .py 6 | # format_name: light 7 | # format_version: '1.5' 8 | # jupytext_version: 1.7.1 9 | # kernelspec: 10 | # display_name: Python 3 11 | # language: python 12 | # name: python3 13 | # --- 14 | 15 | # # Practical Machine Learning for Physicists 16 | 17 | # ## Kernel Density Estimation 18 | # 19 | # This notebook is just a brief aside to demonstrate the method of kernel density estimation 20 | # 21 | # ### The algorithm 22 | # Let $(x_1, x_2, \cdots x_n)$ be independent samples from some dsitribution with unkown density $f$ at any given point $x$. We want to estimate $f$, the kernel density estimator is: 23 | # $$\hat{f}(x) = \frac{1}{n} \sum_{i=1}^n K_{h}(x-x_i) = \frac{1}{nh} \sum_{i=1}^n K \left(\frac{x-x_i}{h} \right)$$ 24 | # where $K$ is the kernel and $h>0$ is known as the bandwidth. In principle, $K$ can be anyone of a number of different functions. In practice, $K$ is often taken as the standard normal distribution (mean of 0, sigma of 1) 25 | 26 | # + 27 | import matplotlib.pyplot as plt 28 | import numpy as np 29 | 30 | import matplotlib.style #Some style nonsense 31 | import matplotlib as mpl #Some more style nonsense 32 | 33 | import scipy.stats as stats 34 | from scipy.stats import gaussian_kde 35 | 36 | #Set default figure size 37 | #mpl.rcParams['figure.figsize'] = [12.0, 8.0] #Inches... of course it is inches 38 | mpl.rcParams["legend.frameon"] = False 39 | mpl.rcParams['figure.dpi']=200 # dots per inch 40 | 41 | # + 42 | xVals=np.random.normal(size=(100)) 43 | 44 | def kde_scipy(x, x_grid, bandwidth=0.2, **kwargs): 45 | """Kernel Density Estimation with Scipy""" 46 | # Note that scipy weights its bandwidth by the covariance of the 47 | # input data. To make the results comparable to the other methods, 48 | # we divide the bandwidth by the sample standard deviation here. 49 | kde = gaussian_kde(x, bw_method=bandwidth / x.std(ddof=1), **kwargs) 50 | return kde.evaluate(x_grid) 51 | 52 | 53 | # - 54 | 55 | fig,ax=plt.subplots() 56 | bins=np.linspace(-3,3,100) 57 | bins2=np.linspace(-3,3,10000) 58 | _= ax.hist(xVals,bins=bins,alpha=.7,label="Data Points",weights=[0.01]*100) 59 | ax.plot(bins,stats.norm.pdf(bins),label="True PDF") 60 | kde=gaussian_kde(xVals) 61 | ax.plot(bins2,kde.evaluate(bins2),label="KDE Optimal") 62 | for bw in [0.05,0.5,2]: 63 | ax.plot(bins2,kde_scipy(xVals,bins2,bw),label='KDE BW='+str(bw)) 64 | ax.legend() 65 | ax.set_xlim([-3,3]) 66 | ax.set_ylim([0,0.65]) 67 | ax.set_xlabel("$x$") 68 | ax.set_ylabel("$\hat{f}(x)$") 69 | 70 | xVals=np.random.normal(size=(100)) 71 | yVals=np.random.normal(size=(100)) 72 | kde=gaussian_kde([xVals,yVals]) 73 | fig,ax=plt.subplots() 74 | ax.plot(xVals,yVals,".",c="r",alpha=0.5) 75 | ax.set_aspect("equal") 76 | ax.set_xlim((-3,3)) 77 | ax.set_ylim((-3,3)) 78 | ax.set_xlabel("$x$") 79 | ax.set_ylabel("$y$") 80 | 81 | 82 | def fofz(z): 83 | # f(z)=z/10 + z/ ||z|| 84 | # There must be a more elegant way of doing this, but the following messy line does work 85 | # actually I quite like the tiling of the n-element long array into a 2xn array 86 | return z/10+z/(np.tile(np.linalg.norm(z,axis=0),(2,1))) 87 | 88 | 89 | z=np.vstack([xVals,yVals]) 90 | fig,ax=plt.subplots() 91 | f=fofz(z) 92 | ax.plot(f[0,:],f[1,:],".",c="r",alpha=0.5) 93 | ax.set_aspect("equal") 94 | ax.set_xlim((-1.5,1.5)) 95 | ax.set_ylim((-1.5,1.5)) 96 | ax.set_xlabel("$x$") 97 | ax.set_ylabel("$y$") 98 | 99 | # ## Plot KDE as heatmap 100 | # 101 | 102 | # + 103 | nbins=200 104 | xi, yi = np.mgrid[-3:+3:nbins*1j, -3:+3:nbins*1j] 105 | array=np.vstack([xi.flatten(), yi.flatten()]) 106 | 107 | zi = kde(array) 108 | # Make the plot 109 | fig,ax=plt.subplots() 110 | ax.pcolormesh(xi, yi, zi.reshape(xi.shape),shading='auto',cmap='viridis') 111 | ax.plot(xVals,yVals,".",c="r",alpha=0.5) 112 | ax.set_aspect("equal") 113 | ax.set_xlim((-3,3)) 114 | ax.set_ylim((-3,3)) 115 | ax.set_xlabel("$x$") 116 | ax.set_ylabel("$y$") 117 | 118 | # - 119 | 120 | 121 | -------------------------------------------------------------------------------- /Week8/Week8_Ising.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # --- 3 | # jupyter: 4 | # jupytext: 5 | # text_representation: 6 | # extension: .py 7 | # format_name: light 8 | # format_version: '1.5' 9 | # jupytext_version: 1.13.2 10 | # kernelspec: 11 | # display_name: Python 3 12 | # language: python 13 | # name: python3 14 | # --- 15 | 16 | # # Practical Machine Learning for Physicists 17 | # 18 | # In this notebook we will illustrate the Markov Chain Monte Carlo technique using an example from physics, a lattice of spin states. 19 | # 20 | # ## Spin and the Ising Model 21 | # 22 | # In the slides we saw that the energy in a spin model when $s_i \in \{-1,+1\}$ was given by: 23 | # $$ E(s) = - \sum_i a_i s_i - \sum_{i,j} J s_i s_j $$ 24 | # where the $a_i$ describes the interactions with an external field and the $J$ terms are the self interaction. 25 | # 26 | # If we ignore the external field contribution and limit the spin-interaction to the nearest neighbours (up-down-left-right on a 2D lattice) then the energy function becomes: 27 | # $$ E(s) = - \sum_{ij,nn} J s_i s_j $$ 28 | # 29 | # To mimic a large areas we can use periodic bundary conditions (so the right-hand side of the right edge is the left edge). 30 | # 31 | # ## Magnetisation 32 | # 33 | # The degree of magnetisation can be characterised as 34 | # $$ M = \frac{1}{N} \sum_{i=1}^N s_i $$ 35 | # 36 | 37 | import numpy as np 38 | import matplotlib.pyplot as plt 39 | import matplotlib 40 | matplotlib.rcParams['figure.dpi']=300 # highres display 41 | from tqdm import tqdm 42 | 43 | Nx=Ny=30 44 | def init_spins(): #Get initial random spin state 45 | spins=np.random.random((Nx,Ny)) # Get random spins 46 | spins=spins>0.5 47 | spins=2*(spins-0.5) #Convert 0-1. to -1 or 1 48 | return spins 49 | 50 | 51 | # ## Plot the spins 52 | # Here we define a function to plot the spins (does it look familiar from Week 7?) 53 | 54 | #Plot the array of -1,+1 spin values as unicode up down arrows. 55 | def plotSpins(spinVals,title=None): 56 | fig, ax = plt.subplots(figsize=(2,2)) 57 | ax.axis('tight') 58 | ax.axis('off') 59 | nRow=spinVals.shape[0] 60 | nCol=spinVals.shape[1] 61 | arrows='⇩⇧' 62 | spinArrow=[[ arrows[int(val>0)] for val in row ] for row in spinVals ] 63 | 64 | the_table = ax.table(spinArrow,loc='center',cellLoc='center') 65 | for pos, cell in the_table._cells.items(): 66 | cell._height = cell._width = 1./nRow 67 | if title: 68 | ax.set_title(title) 69 | 70 | 71 | spins=init_spins() 72 | plotSpins(spins[0:10,0:10],title="Initial Condition") #Only plot a 10x10 square as it gets too crowded otherwise 73 | fig,ax=plt.subplots() 74 | ax.imshow(spins,cmap='binary') 75 | 76 | 77 | # + 78 | # Calculate the total energy in the spin array using 79 | # E = sum ( - J s_i s_j) 80 | # where the sum is only over the nearest neighbours (up, down and left, right) 81 | # using periodic boundary conditions on the 2-D grid. 82 | # Inputs: spinarray, 2-D array of spins (-1 or +1) 83 | # J is energy of each spin interaction 84 | # Return: Total energy 85 | def get_energy(spinarray,J): 86 | middle = spinarray 87 | up = np.roll(spinarray,+1,axis=0) # array shift along axis=0 88 | right= np.roll(spinarray,+1,axis=1) # array shift along axis=1 89 | total = np.sum((up + right)*middle) 90 | return -J*total #total energy 91 | 92 | print("Energy: ",get_energy(spins,1)) 93 | 94 | 95 | # - 96 | 97 | # ## The ~~Metropolis~~ Rosenbluth-Hastings Algorithm 98 | # 99 | # The ~~Metropolis~~ Rosenbluth-Hastings algorithm is: 100 | # 1. Pick a random point in the grid 101 | # 2. Compute the energy difference in the spin in that location is flipped, $dE$ 102 | # 3. If $dE<0$ flip the spin, otherwise randomly flip the spin with probability $p(dE) = e^{- \beta dE}$ where $\beta=\frac{1}{k_{B}T}$ 103 | 104 | def mcmh_step(spins,E1,T,J): 105 | ij=np.random.randint(Nx,size=(2)) 106 | i=ij[0] 107 | j=ij[1] 108 | sij=spins[i][j] 109 | spins[i][j]=-1*sij 110 | E2=get_energy(spins,J) 111 | dE=E2-E1 112 | if dE < 0: 113 | return spins,E2 114 | if np.random.random(1)