A visual proof that neural nets can approximate any function
neuralnetworksanddeeplearning.com
neuralnetworksanddeeplearning.com
To clarify, I'm not trying to make a snippy remark, I just happened to have used polynomial curve fitting before and looked up the Wikipedia page for the Stone-Weierstrass theorem and am trying to figure out the relevance of that post on NNs. Is it essentially the same claim?
Any clarification appreciated!
- [1] http://mathworld.wolfram.com/WeierstrassApproximationTheorem...
- [2] http://mathworld.wolfram.com/Stone-WeierstrassTheorem.html
Neural Networks use a different "basis" (sigmoid, ReLU, etc.), but the underlying idea shares the same spirit.
All that’s really needed is that the limit of the NN basis function is different at plus versus minus infinity on the real line. This will give you the “separates points “ property.
The fact that NN can reproduce arbitrary functions is decidedly not what makes them special...
Extrapolation? I was under the impression that generalizability of NNs beyond the training data was one of the major problems faced by NNs.
For neural networks, if you take something basic like sorting a list or multiplying two decimal numbers, the further you are from range the models were trained on, the worse they will do (yes, transformers too). Only exception I can think of are carefully trained Neural GPUs, which will quickly struggle to be 100% correct as you depart simple tasks. While consuming a great deal of computational resources. Program synthesis is the general area, with no approach clearly dominant in the same way deep learning has dominated machine learning.
As a for instance, here's an interesting paper I found out about from HN that describes how image classifiers trained on one standard dataset (ImageNet etc) do much worse on other standard datasets and how it's even possible to identify the dataset a classifier was trained on:
Unbiased look at dataset bias
https://people.csail.mit.edu/torralba/publications/datasets_...
Which leads into unknowingly building NNs that are actually building classification networks and not realizing approximations might not fit into your model.
From section 4.6.2 of Tom Mitchell's Machine Learning book: "Arbitrary functions. Any function can be approximated to arbitrary accuracy by a network with three layers of units (Cybenko 1988)."
It depends on how you measure the distance between functions. If you are using the uniform norm (as is used in the universal approximation theorem) then this is false.
The real question is whether the approximation is a good one:
- can you prove error bounds ?
- can you bound the maximum error?
- is it efficient ? (low storage, low computational effort)
- is it fast to build? (low computational effort of coefficients)
- derivatives: how well does it approximate gradients, what's the error on the gradient, is it bounded? can one bound it, how fast can one evaluate them, etc.
- there are many other interesting properties: https://en.wikipedia.org/wiki/Approximation_theory
From pretty much every single aspect of approximation theory, neural nets are one of the worst methods to approximate a continuous function. If you were to make an analogy with sorting algorithms, they would be worse than bogosort. There are no error bounds, you can't bound the maximum error, computing their coefficients is very slow (training, needs GPUs, ...), they require a lot of storage and computational power to evaluate, ...
What about scalability? I don't know of many approximation methods that can routinely work with the amount of coefficients, datapoints, dimensionality of data etc. that neural networks are coping with. (Though AIUI compressed sensing methods might come close; compressed sensing can be seen as a kind of approximation as well.)
Piecewise linear regression is a universal function approximator.
Drag the sliders for w and n to change how step-like the sigmoids are and how many are combined. The purple lines are the sigmoids, relative changes at each (regularly spaced) position, which are added together to make the blue approximation to the red function. You can change the function f(x) to see how it handles other possibilities, including piecewise/discontinuous ones like "{x<.5: 0, x>=5: x}".
I couldn't find a nice way of making the slider logarithmic (in Desmos the only way to do it is with an intermediate variable, which is kind of confusing), so I reduced the maximum number on the slider. I also fixed a bug.
It seems the choice of function inside the neuron is kindof arbitary or is it locked to the sigmoid function? If so you could put cos and i*sin as function in your neurons and your neural net essentially becomes DFT?
Okay, so what? You require more and more neurons (ie. parameters) to approximate your function better and better. You can do the same with piecewise constant (Riemann sums). You can do this with trig functions too (Fourier transform).
"This result tells us that neural networks have a kind of universality."
I don't know what this statement means. What mathematical properties do neural networks have that other functions don't? The ability to approximate continuous functions isn't special. Given 5 points, I can perfectly fit an elephant to your function. And it's not like you are fitting the function with as few parameters as possible.
If the continuous function is additive, it's linear. If it's nonlinear, you can differentiate it to obtain a linear approximation. A neural network computes linear transformations, so unless I'm missing something I'm a little surprised there's a substantive theorem for this. Is it not a corollary on the fact that we can construct a vector space of all continuous functions?
Pretty much, but you have to show that neural networks can create a basis in that vector space which is essentially the proof presented in the article.
> If the continuous function is additive, it's linear. If it's nonlinear, you can differentiate it to obtain a linear approximation.
Differentiating to obtain a linear approximation does not give you an arbitrarily good approximation like the theorem does.
> A neural network computes linear transformations, so unless I'm missing something I'm a little surprised there's a substantive theorem for this. Is it not a corollary on the fact that we can construct a vector space of all continuous functions?
Neural networks using sigmoid transfer functions do not compute linear transformations anymore.
Importantly this theorem also states that you can approximate any function with only two hidden layers. A similar proof could not be made for a single hidden layer so it seems that the non-linearity of a single layer is not enough to form a basis for all continuous functions.
> A neural network computes linear transformations
They compute a nonlinear function of an affine transform. Neural networks are nonlinear functions.
The set of all (real) functions is also linear, but is a lot trickier to work with.
The standard proof uses some functional analysis techniques but nothing too complicated to show you can get arbitrarily close to any continuous function with an NN. That includes things like step functions whose derivatives are not defined everywhere.
If you are using gradient descent, then you'll need the desired loss function to be differentiable with respect to the parameters, but that's a totally different matter.
In practice, however, the input to neural networks is represented by floating point values, which is a discrete set. So pick whatever arbitrary function you would like, there is some continuous approximation to that function which is actually equal to it on every floating point value, and that function can be approximated arbitrarily closely by a neural network.
Is it data or is it something can be optimised.
```
celsius_q = np.array([-40, -10, 0, 8, 15, 22, 38], dtype=float)
fahrenheit_a = np.array([-40, 14, 32, 46, 59, 72, 100], dtype=float)
for i,c in enumerate(celsius_q): print("{} degrees Celsius = {} degrees Fahrenheit".format(c, fahrenheit_a[i]))
l0 = tf.keras.layers.Dense(units=1, input_shape=[1])
model = tf.keras.Sequential([l0])
model.compile(loss='mean_squared_error', optimizer=tf.keras.optimizers.Adam(0.1)) history = model.fit(celsius_q, fahrenheit_a, epochs=500, verbose=False)
print("Finished training the model")
print(model.predict([100.0])) // it results 211.874 which is not 100% accurate (100×1.8+32=212)
```
What can be done to make this NN 100% accurate for simple linear equation 𝑓=1.8𝑐+32
https://colab.research.google.com/github/tensorflow/examples...
* Tune the hyperparameters. In particular, tune the learning rate. To quote the Deep Learning Book [0]:
> The learning rate is perhaps the most important hyperparameter. If you have time to tune only one hyperparameter, tune the learning rate. It controls the effective capacity of the model in a more complicated way than other hyperparameters—the effective capacity of the model is highest when the learning rate is correct for the optimization problem, not when the learning rate is especially large or especially small.
The following code will yield exactly 212 almost every run (using fixed data and a different choice of learning rate):
```
celsius_q = np.array([-40, -10, 0, 8, 15, 22, 38], dtype=float)
fahrenheit_a = np.array([x * 1.8 + 32 for x in celsius_q], dtype=float)
for i, c in enumerate(celsius_q):
print("{} degrees Celsius = {} degrees Fahrenheit".format(c, fahrenheit_a[i]))
l0 = tf.keras.layers.Dense(units=1, input_shape=[1])model = tf.keras.Sequential([l0])
model.compile(loss='mean_squared_error', optimizer=tf.keras.optimizers.Adam(lr=1.0))
history = model.fit(celsius_q, fahrenheit_a, epochs=500, verbose=False)
print("Finished training the model")
print(model.predict([100.0]))
```
[0] https://www.deeplearningbook.org/contents/guidelines.html
celsius_q = np.array([-40, -10, 0, 8, 15, 22, 38], dtype=float)
fahrenheit_a = np.array([x * 1.8 + 32 for x in celsius_q], dtype=float)
for i, c in enumerate(celsius_q):
print("{} degrees Celsius = {} degrees Fahrenheit".format(c, fahrenheit_a[i]))
l0 = tf.keras.layers.Dense(units=1, input_shape=[1])
model = tf.keras.Sequential([l0])
model.compile(loss='mean_squared_error', optimizer=tf.keras.optimizers.Adam(lr=1.0))
history = model.fit(celsius_q, fahrenheit_a, epochs=500, verbose=False)
print("Finished training the model")
print(model.predict([100.0]))Neural networks are much better suited for distilling down and compressing very complex high dimensional data though anyways, and you really don't need to be using them for problems like this. It's completely overkill in addition to being very computationally inefficient. There's nothing wrong with just simply using linear regression. In many cases it's the right choice.
In your toy problem case you coded above, you are effectively just doing linear regression, except you added in an Adam gradient descent optimizer instead of just doing least squares, which by the way would have been infinitely faster and immediately given you an answer.
And also what I learned in school which is doing linear regression using a function with more degrees of freedom than the data tends to generate garbage. It can match the data points exactly and then be wildly off between them.
It's a simplification, but informative about some ML techniques.
https://en.m.wikipedia.org/wiki/Runge's_phenomenon
and can be mitigated eg by non-uniform interpolation grids like chebychev nodes.
However, this kills the neural network as a general purpose computation device.
https://people.maths.ox.ac.uk/trefethen/atapvideos.html
Chebfun is pretty cool too!
Here's an example:
https://apps.axibase.com/chartlab/9922f98f
* Chart 1. Function value for x in [0, 1).
* Chart 2. Function value for x in [0, 2).
* Chart 3. Function value for x in [0, 1) and extrapolated values for x in [1, 2).
A) was focusing on functions that take a certain amount of input variables and
B) that the function (that s/he mirrored using the neural net) computes out of it directly one or more of result(s).
C) To do that s/he used a backpropagation network (which is the only model I know very well).
Right or wrong?
EDIT: when I say "directly" I mean that the function(s) does not feed itself.
> The explanation for universality we've discussed is certainly not a practical prescription for how to compute using neural networks! In this, it's much like proofs of universality for NAND gates and the like. For this reason, I've focused mostly on trying to make the construction clear and easy to follow, and not on optimizing the details of the construction. However, you may find it a fun and instructive exercise to see if you can improve the construction.
Another caveat that I forgot in my previous comment is the domain has to be compact (closed and bounded). But if so, then it doesn’t really matter how weird your continuous function is, because compactness of the domain guarantees uniform continuity, i.e. your delta only depends on epsilon and not x in the epsilon-delta criterion of continuity. That allows you to partition the domain into patches of diameter delta, in which very simple functions are sufficient to approximate within epsilon.
Just my two cents, correct me if I'm wrong.
Technically something capable of arbitrary computation in the Turing machine sense can be stronger than a Turing machine (the obvious example being a Turing machine with access to a halting oracle).
Also if you want to show something is limited by the capabilities of a Turing machine it's way easier to point out it's being run on a Turing machine, as opposed to showing it's capable of arbitrary computation (which might not even be sufficient, as I explained above).
As it stands it's not entirely obvious that a neural network with access to arbitrary precision arithmetic might not be more powerful than a Turing machine, but since we couldn't possibly construct a neural network precise enough that's a bit of a moot point.
So-called "neural nets" are just logistic regression with a fancy name. Seems "deep learning" is just a wavelet transform with a sigmoid basis. (So, boring math stuff we already knew forever, plus marketing mumbo-jumbo.)
Well... more like an iterated transform.
You're right, most of the mathematics is very old indeed. What changed was the hardware (parallelism), software (easy-to-use autodiff packages) and the availability of data.
There's a lot of hype in the field, but some of that hype is deserved. Computer vision was practically in crisis in the late 00's and early 10's. No significant progress was being made on problems, and there were few strategic directions to move in that hadn't been done to death already. Then smash: along comes deep learning, which changed everything.
For a vanilla MLP, you'd need to add in a few previous values (ie you'd predict x_{t+1} = f(x_t, ..., x_{t-N}), where f is your neural network and N is some fixed integer).
Check this out: https://www.desmos.com/calculator/rfaqogkbmy
Try changing f(x) to "sin(x)" or whatever you like (e.g. sin(10x) may be more interesting). Then drag the sliders for w (how step-like the purple pieces are) and n (how many pieces to add together). The function f(x) is red, and the approximation is blue.
The original article is about neural networks being able to represent any function (for some definition of any).
I was just pointing out that there exists much cheaper ways of representing any function. Therefore the article seems very unexciting to me.
Btw, you have chose L^2(R) yourself and then used that to show that there are interesting function not in the space you have chosen, quite a circular argument.
Since the article on neural networks never mentions functions defined on a infinite domain, one can easily take L^2([0,1]) or L^2([0,Lambda]) up to some cutoff Lambda. I would say that all non-pathological functions you can think of are there!
> I was just pointing out that there exists much cheaper ways of representing any function. Therefore the article seems very unexciting to me.
To be fair, your original comment didn't really make a point. What kind of cheaper representations do you have in mind? What makes an orthogonal basis of functions too "expensive" a representation for your taste?
> I would say that all non-pathological functions you can think of are there!
I'd argue that most "real functions" that we care to learn (e.g. mappings between high dimensional data and labels) are pathological. In this sense, we should really care about the completeness of these spaces, perhaps even more than the well-behaved ones.
All physics assumes you are dealing with non-pathological functions, except for some really particular cases. You can do nearly everything in Electromagnetism and nearly all Quantum Mechanics with non pathological functions.
Maybe we have a different definition of pathological, I am using it in the way a physicist would use (i.e. continuous, continuous derivatives, so on)
The kind of pathological function that I'm referring to is neither of these. For example, what does the manifold of all 1 second clips of the word "the" look like? If the clip is sampled at 60 Hz, each clip is already in 60d space. I'm inclined to think that it's some unimaginably complicated manifold that would likely fall into the category of "edge cases", which previous commenters have mentioned and it sounds like you're discounting as nitpicking.
I don't know if this aligns with what you mean by a pathological function, and I'm happy to continue having this discussion with a more concrete example of what you mean. :)