Atomic Machine Learning is a group of Machine Learning algorithms based on Atomic Functions and Atomic Strings.
AML theory is being developed in ResearchGate project https://www.researchgate.net/project/Atomic-Machine-Learning-and-Artificial-Intelligence-with-Atomic-Soliton-and-R-functions by Professor Sergei Yurievich Eremenko https://www.researchgate.net/profile/Sergei_Eremenko.
The file contains Python script for Atomic Function, Atomic String, Atomic Sigmoid and Atomic Gaussian.
Atomic Function (https://ru.wikipedia.org/w/index.php?oldid=82669103) discovered in 1970th by Academician of National Academy of Sciences of Ukraine Rvachev V.L. (https://ru.wikipedia.org/w/index.php?oldid=83948367) and Professor Rvachev V.A. and advanced by many followers notably Professor Kravchenko V.F. (https://ru.wikipedia.org/w/index.php?oldid=84521570).
Atomic String (AString) as a generalization/integral of an Atomic Function is introduced by the author, Professor Sergei Yu. Eremenko (https://www.researchgate.net/profile/Sergei_Eremenko, https://au.linkedin.com/in/sergei-eremenko-3862079), in paper "Atomic Strings and Fabric of Spacetime" https://www.researchgate.net/publication/320457739
The theory of atomic functions (AF) evolving since 1970th has found many applications in different branches of mathematics and physics, and now we explore its applicability for a data science domain of Machine Learning. Pulse-like AF can be used to build atomic kernel in Support Vector Machines to describe proximity to singular landmarks and ultimately define complex Decision Boundaries. Atomic local weighted regression can be build by introducing the AF weight function in locally weighted scatterplot smoothing (LOESS) technique. AString as an integral from AF can be the foundation of atomic regression and atomic activation function for Neural Networks. Unsuperwised Machine Learning algorithms like Principal Component Analysis, Dimensionality Reduction and Density Estimations can also use AF and AString which have unique properties of compact support, fast calculation of derivatives via themselves and ability to exactly represent sections of polynomials and other functions widely used in statistics. AF as a probabilistic weighted distribution of uniformly random variables is deeply related to Prouhet–Thue–Morse sequence which may have more relevance for some fair games and sequencing processes. Multiple real Matlab, R and Python examples calculate complex decision boundaries and regressions. The concepts of an atomic computer and calculus are also discussed. In combination, these methods compose Atomic Machine Learning theory which extends the 50 years’ history of AFs and their generalizations to new scientific domains.
##########################################################
##This script introduces Atomic Function and Atomic String
##########################################################
import numpy as np
import pylab as pl
################### One Pulse of atomic function
def up1(x: float) -> float:
#Atomic function table
up_y = [0.5, 0.48, 0.460000017,0.440000421,0.420003478,0.400016184, 0.380053256, 0.360139056, 0.340308139, 0.320605107,
0.301083436, 0.281802850, 0.262826445, 0.244218000, 0.226041554, 0.208361009, 0.191239338, 0.174736305,
0.158905389, 0.143991189, 0.129427260, 0.115840866, 0.103044024, 0.9110444278e-01, 0.798444445e-01, 0.694444445e-01,
0.598444445e-01, 0.510444877e-01, 0.430440239e-01, 0.358409663e-01, 0.294282603e-01, 0.237911889e-01, 0.189053889e-01,
0.147363055e-01, 0.112393379e-01, 0.836100883e-02, 0.604155412e-02, 0.421800000e-02, 0.282644445e-02, 0.180999032e-02,
0.108343562e-02, 0.605106267e-03, 0.308138660e-03, 0.139055523e-03, 0.532555251e-04, 0.161841328e-04, 0.347816874e-05,
0.420576116e-05, 0.167693347e-07, 0.354008603e-10, 0]
up_x = np.arange(0.5, 1.01, 0.01)
res = 0.
if ((x>=0.5) and (x<=1)):
for i in range(len(up_x) - 1):
if (up_x[i] >= x) and (x < up_x[i+1]):
N1 = 1 - (x - up_x[i])/0.01
res = N1 * up_y[i] + (1 - N1) * up_y[i+1]
return res
return res
############### Atomic Function Pulse with width, shift and scale #############
def upulse(t: float, a = 1., b = 0., c = 1., d = 0.) -> float:
x = (t - b)/a
res = 0.
if (x >= 0.5) and (x <= 1):
res = up1(x)
elif (x >= 0.0) and (x < 0.5):
res = 1 - up1(1 - x)
elif (x >= -1 and x <= -0.5):
res = up1(-x)
elif (x > -0.5) and (x < 0):
res = 1 - up1(1 + x)
res = d + res * c
return res
############### Atomic Function Applied to list with width, shift and scale #############
def up(x: list, a = 1., b = 0., c = 1., d = 0.) -> list:
res: list = []
for i in range(len(x)):
res.append(upulse(x[i], a, b, c, d))
return res
x = np.arange(-2.0, 2.0, 0.01)
pl.title('Atomic Function')
pl.plot(x, up(x), label='Atomic Function')
pl.grid(True)
pl.show()
############### Atomic String #############
def AString1(x: float) -> float:
res = 1 * (upulse(x/2.0 - 0.5) - 0.5)
return res
############### Atomic String Pulse with width, shift and scale #############
def AStringPulse(t: float, a = 1., b = 0., c = 1., d = 0.) -> float:
x = (t - b)/a
if (x < -1):
res = -0.5
elif (x > 1):
res = 0.5
else:
res = AString1(x)
res = d + res * c
return res
###### Atomic String Applied to list with width, shift and scale #############
def AString(x: list, a = 1., b = 0., c = 1., d = 0.) -> list:
res: list = []
for i in range(len(x)):
res.append(AStringPulse(x[i], a, b, c, d))
#res[i] = AStringPulse(x[i], a, b, c)
return res
###### Summation of two lists #############
def Sum(x1: list, x2: list) -> list:
res: list = []
for i in range(len(x1)):
res.append(x1[i] + x2[i])
return res
pl.title('Atomic String')
pl.plot(x, AString(x, 1.0, 0, 1, 0), label='Atomic String')
pl.grid(True)
pl.show()
#This Calculates Derivative
dx = x[1] - x[0]
dydx = np.gradient(up(x), dx)
pl.plot(x, up(x), label='Atomic Function')
pl.plot(x, AString(x, 1.0, 0, 1, 0), label='Atomic String')
pl.plot(x, dydx, label='A-Function Derivative')
pl.title('Atomic Function and String')
pl.legend(loc='best', numpoints=1)
pl.grid(True)
pl.show()
1) Remarkably, Atomic Function Derivative can be exressed via Atomic Function itself - up'(x)= 2up(2x+1)-2up(2x-1) meaning the shape of pulses for derivative function can be represented by shifted and stratched Atomic Function itself - remarkable property
2) The Atomic Function pulses superposition set at points -2, -1, 0, +1, +2... can exactly represent a Unity (number 1): 1 = ... up(x-3) + up(x-2) + up(x-1) + up(x-0) + up(x+1) + up(x+2) + up(x+3) + ...
pl.plot(x, up(x, 1, -1), linewidth=1, label='Atomic Function at x=-1')
pl.plot(x, up(x, 1, +0), linewidth=1, label='Atomic Function at x=0')
pl.plot(x, up(x, 1, -1), linewidth=1, label='Atomic Function at x=-1')
pl.plot(x, Sum(up(x, 1, -1), Sum(up(x), up(x, 1, 1))), linewidth=2, label='Atomic Function Compounding')
pl.title('Atomic Function Compounding represent 1')
pl.legend(loc='best', numpoints=1)
pl.grid(True)
pl.show()
3) Atomic Function (AF) is a 'finite' function (like spline) not equal to zero only on section |x|<=1
4) Atomic Function is a non-analytical function (can not be represented by Taylor's series), but with known Fourier Transformation allowing to exactly calculate AF in certain points, with tabular representation provided in script above.
1) Astring is an solition kink-like function - Integral of Atomic Function (AF) which can be expressed via AF itself: AString(x) = Integral(0,x)(Up(x)) = Up(x/2 - 1/2) - 1/2
2) Atomic Function can be represented via simple superposition of Atomic Strings: up(x) = AString(2x + 1) - AString(2x - 1)
######### Presentation of Atomic Function via Atomic Strings ##########
x = np.arange(-2.0, 2.0, 0.01)
pl.plot(x, AString(x, 1, 0, 1, 0), '--', linewidth=1, label='AString(x)')
pl.plot(x, AString(x, 0.5, -0.5, +1, 0), '--', linewidth=2, label='+AString(2x+1)')
pl.plot(x, AString(x, 0.5, +0.5, -1, 0), '--', linewidth=2, label='-AString(2x-1)')
#pl.plot(x, up(x, 1.0, 0, 1, 0), '--', linewidth=1, label='Atomic Function')
AS2 = Sum(AString(x, 0.5, -0.5, +1, 0), AString(x, 0.5, +0.5, -1, 0))
pl.plot(x, AS2, linewidth=3, label='Up(x) via Strings')
pl.title('Atomic Function as a Combination of AStrings')
pl.legend(loc='center left', numpoints=1)
pl.grid(True)
pl.show()
3) All derivatives of AString can be represented via AString itself: AString'(x) = AString(2x + 1) - AString(2x - 1)
4) Combination of Atomic Strings can exactly represent a straight line: x = AString(x) + Astring(x+1) + Astring(x+2)...
x = np.arange(-40.0, 40.0, 0.01)
#pl.plot(x, ABline (x, 1, 0), label='ABLine 1*x')
pl.plot(x, AString(x, 10.0,-15, 10, -15), '--', linewidth=1, label='AString 1')
pl.plot(x, AString(x, 10.0, -5, 10, -5), '--', linewidth=1, label='AString 2')
pl.plot(x, AString(x, 10.0, +5, 10, +5), '--', linewidth=1, label='AString 3')
pl.plot(x, AString(x, 10.0,+15, 10, +15), '--', linewidth=1, label='AString 4')
AS2 = Sum(AString(x, 10.0, -15, 10, -15), AString(x, 10., -5, 10, -5))
AS3 = Sum(AS2, AString(x, 10, +5, 10, +5))
AS4 = Sum(AS3, AString(x, 10,+15, 10, +15))
pl.plot(x, AS4, label='AStrings Joins', linewidth=2)
pl.title('Atomic Strings Combinations')
pl.legend(loc='best', numpoints=1)
pl.grid(True)
pl.show()
x = np.arange(-30.0, 30.0, 0.01)
#pl.plot(x, ABline (x, 1, 0), label='ABLine 1*x')
pl.plot(x, AString(x, 10.0,-15, 10, -15), '--', linewidth=1, label='AString Quantum 1')
pl.plot(x, AString(x, 10.0, -5, 10, -5), '--', linewidth=1, label='AString Quantum 2')
pl.plot(x, AString(x, 10.0, +5, 10, +5), '--', linewidth=1, label='AString Quantum 3')
pl.plot(x, AString(x, 10.0,+15, 10, +15), '--', linewidth=1, label='AString Quantum 4')
AS2 = Sum(AString(x, 10.0, -15, 10, -15), AString(x, 10., -5, 10, -5))
AS3 = Sum(AS2, AString(x, 10, +5, 10, +5))
AS4 = Sum(AS3, AString(x, 10,+15, 10, +15))
pl.plot(x, AS4, label='Spacetime Dimension', linewidth=2)
pl.title('Representing of a Continuuum by joining of AStrings')
pl.legend(loc='best', numpoints=1)
pl.grid(True)
pl.show()
x = np.arange(-50.0, 50.0, 0.1)
dx = x[1] - x[0]
CS6 = Sum(up(x, 5, -30, 5, 5), up(x, 15, 0, 15, 5))
CS6 = Sum(CS6, up(x, 10, +30, 10, 5))
pl.plot(x, CS6, label='Continuum Density')
IntC6 = np.cumsum(CS6)*dx/50
pl.plot(x, IntC6, label='Continuum Shape')
DerC6 = np.gradient(CS6, dx)
pl.plot(x, DerC6, label='Continuum Curvature')
pl.title('Curved Continuum')
pl.legend(loc='best', numpoints=1)
pl.grid(True)
pl.show()
# Plot combined function
x = np.arange(-6.0, 6.0, 0.01)
gaussian = np.exp(-x*x/2)
pl.plot(x, gaussian, label='Gaussian')
pl.plot(x, up(x,3), label='Atomic Function')
pl.title('Gaussian and Atomic Function')
pl.legend(loc='best', numpoints=1)
pl.grid(True)
pl.show()
# Plot combined function
x = np.arange(-6.0, 6.0, 0.01)
sigmoid = 1./(1.+ np.exp(-x))
pl.plot(x, sigmoid, label='Sigmoid')
pl.plot(x, AString(x, 4.0, 0, 1, 0.5), label='Atomic String')
pl.title('Sigmoid and Atomic String Functions')
pl.legend(loc='best', numpoints=1)
pl.grid(True)
pl.show()
# Plot combined function
x = np.arange(-1.0, 1.0, 0.01)
cubic = np.power(1.-np.abs(x*x*x), 3);
pl.plot(x, cubic, label='Three-Cube Function')
pl.plot(x, up(x,1), label='Atomic Function')
pl.title('Three-Cube and Atomic Function')
pl.legend(loc='best', numpoints=1)
pl.grid(True)
pl.show()
###### Fabius Function Applied to list with width, shift and scale #############
def Fabius(x: list, a = 1.0, b = 0, c = 1., d = 0) -> list:
res: list = []
for i in range(len(x)):
res.append(AStringPulse(x[i], 0.5*a, 0.5 + b, 1.0*c, 0.5 + d))
return res
############### Plotting Atomic and String Functions ##############
x = np.arange(0.0, 1.01, 0.01)
#pl.plot(x, AString(x, 0.5, 0.5, 1, 0.5), label='Atomic String 0.5, 0.5, 1, 0.5')
pl.plot(x, Fabius(x), label='Fabius Function via AString')
pl.title('Fabius Function via AString')
pl.legend(loc='best', numpoints=1)
pl.grid(True)
pl.show()
Apart from standard Python code, this script and material is the intellectual property of Professor Sergei Yu. Eremenko (https://au.linkedin.com/in/sergei-eremenko-3862079). You may not reproduce, edit, translate, distribute, publish or host this document in any way without the permission of Professor Eremenko.