Advertisement
larsupilami73

Central Limit Theorem Demo

Dec 9th, 2019
323
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.82 KB | None | 0 0
  1. #!/usr/bin/python3
  2. #
  3. #Central Limit Theorem Demo:
  4. # Suppose X_tot = X_1 + ... + X_n, with each X_i following some distribution X_i ~ D,
  5. # then X_tot tends to a normal distribution: X ~N(\mu, \sigma), for n-> \infty
  6. #
  7. #larsupilami73
  8.  
  9. import os
  10. from scipy import *
  11. from scipy.stats import norm
  12. import matplotlib.pyplot as plt
  13.  
  14.  
  15. random.seed(42)
  16. N = 10000 #number of samples to construct
  17.  
  18.  
  19. #generate samples from a weird distribution D
  20. #that does not look like a normal distribution
  21. def some_weird_distribution(Nsamples):
  22.     X= []
  23.     n = 0
  24.     while(n<Nsamples):
  25.         x = random.uniform(0,1) #uniform with a hole, couldn't be further from normal...
  26.         if x<0.2 or x>0.8:
  27.             X.append(x)
  28.             n +=1
  29.     return array(X)
  30.  
  31.  
  32. #see more color names: plt.cm.colors.cnames
  33. c1 = 'tomato'
  34. c2 = 'steelblue'
  35. c3 = 'ivory'
  36. c4 = 'black'
  37. c5 = 'green'
  38.  
  39.  
  40. #temp directory for the frames
  41. if not os.path.exists('./frames'):
  42.     os.mkdir('./frames')
  43. try:
  44.     os.system('rm ./frames/frame*.png')
  45. except:
  46.     pass
  47.  
  48. #now generate sums of the weird distribution
  49. #and show that the sum approximates a normal distribution
  50. #regardless of what the weird distribution looks like!
  51. fig, (ax1,ax2) = plt.subplots(1,2,figsize=(8,4),dpi=100)
  52.  
  53. #get the samples from the weird non-gaussian distribution
  54. x = some_weird_distribution(N)
  55. for k in [1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,24,28,32,36,40]:
  56.    
  57.     #samples
  58.     ax1.scatter(range(N),x, c=c2, s=40,marker='.',alpha=0.4,edgecolor='white', linewidth=0.2,label='K={}\nN={}'.format(k,N))
  59.     ax1.set_title(r'Samples: $X_{tot} = X_1 + \dots +X_{' + '%d'%k +r'}$',fontsize=10)
  60.     ax1.set_ylabel('sample values')
  61.     ax1.set_xlabel('sample nr.')
  62.     ax1.set_ylim(-0.1,1.1)
  63.     ax1.set_yticks([0,0.2,0.4,0.6,0.8,1.0])
  64.     ax1.set_facecolor(c3)
  65.     ax1.legend(loc='upper right',fontsize=9,markerscale=1.4)
  66.  
  67.     #histogram
  68.     n, bins, patches = ax2.hist(x, bins=50,color=c1,density=True,edgecolor=c4,alpha=0.8)
  69.     ax2.set_title(r'Histogram of $X_{tot}$',fontsize=10)
  70.     ax2.set_ylabel('bin values')
  71.     ax2.set_xlabel('sample values')
  72.     ax2.set_xlim(-0.1,1.1)
  73.     ax2.set_ylim(0,6.5)
  74.     ax2.set_facecolor(c3)
  75.  
  76.     #add best fit normal to graph
  77.     (mu, sigma) = norm.fit(x)
  78.     y = norm.pdf(bins, mu, sigma)
  79.     label = r'$\mu=%.3f$'%mu
  80.     label +='\n'
  81.     label +=  r'$\sigma=%.3f$' %sigma
  82.     l = ax2.plot(bins, y, 'r--', linewidth=2.5,label=label,color=c4)
  83.     ax2.legend(loc='upper right',fontsize=9,markerscale=0.5,handlelength=0.75)
  84.    
  85.     #save a frame
  86.     fig.tight_layout()
  87.     fig.savefig('./frames/frame%05d.png' %k)
  88.     ax1.clear()
  89.     ax2.clear()
  90.     #fig.show()
  91.    
  92.     #add samples of the same distribution to x, to get new samples
  93.     #and renormalization so each vector has the same weight
  94.     x = (k*x + some_weird_distribution(N))/(k+1)
  95.    
  96. plt.close('all')   
  97. #now assemble all the pictures in a gif (requires imagemagick)
  98. os.system('convert -delay 100 -loop 0 ./frames/*.png clt.gif')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement