Deep Learning Mathematica
Deep Learning Mathematica
M. M. Hammad
HAL Authorization
Frontmatter
Mohamed M. Hammad
2024 i
FRONTMATTER
M. M. Hammad
Department of Mathematics and Computer Science
Faculty of Science
Damanhour University, Egypt
[Link]
m_hammad@[Link]
ii
FRONTMATTER
To
my
mother
iii
FRONTMATTER
Abstract
"Neural Network and Deep Learning with Mathematica" provides a comprehensive examination of the core challenges
in neural network research and development, utilizing Mathematica's advanced computational capabilities.
Mathematica's integration of symbolic and numeric computation allows for the precise formulation and analysis of
neural network models, making it an invaluable tool for researchers and practitioners alike. Readers will benefit from
Mathematica's extensive library of built-in functions, which simplifies the construction and training of neural
networks, as well as its seamless integration with data visualization, statistical analysis, and image processing tools.
The book addresses critical aspects of neural network methodologies, including model generalization, regularization,
and optimization. It offers in-depth coverage of multilayer feed-forward neural networks, training processes, and
optimization issues such as activation function saturation, vanishing and exploding gradients, and weight initialization.
Advanced topics include complex-valued neural networks and sophisticated activation functions, with detailed
exploration of their properties and applications. Key methodologies discussed include various learning rate schedules,
adaptive algorithms, and techniques for hyperparameter tuning, such as Bayesian optimization and Gaussian
processes. With detailed code examples, step-by-step explanations, and illustrative figures, this book is not only a
resource for beginners but also a valuable reference for seasoned professionals in fields such as data science, machine
learning, and engineering. We have created more than 200 manipulates cover different scenarios in neural networks,
more than 500 light Mathematica codes (examples). The code will run as-is with no code from prior algorithms or
third parties required beyond the installation of Mathematica. Whether you are a student, researcher, or practitioner,
"Neural Network and Deep Learning with Mathematica" equips you with the knowledge and tools to overcome the
complexities of modern artificial intelligence and contribute to the ongoing advancements in this exciting field.
iv
FRONTMATTER
Preface
In the rapidly evolving landscape of artificial intelligence and machine learning, neural networks and deep learning
have emerged as pivotal technologies, revolutionizing fields ranging from image recognition to natural language
processing. As these techniques continue to advance, the challenges associated with their implementation,
optimization, and understanding have become increasingly complex. Addressing these challenges requires not only a
deep theoretical understanding but also practical tools that can bridge the gap between abstract concepts and real-
world applications. This book, Neural Network and Deep Learning with Mathematica, is designed to provide a
comprehensive exploration of the key challenges faced in neural network and deep learning research and development,
alongside practical solutions implemented using Mathematica.
There are several reasons why one might choose Mathematica for neural networks and deep learning:
• Unified Symbolic and Numeric Computation: Mathematica's strength lies in its ability to seamlessly
integrate symbolic and numeric computations. This allows users to define neural network models using
symbolic expressions and directly analyze their properties or gradients before moving to numerical
implementation. This unique feature is particularly valuable for researchers who need to explore
mathematical formulations or derive analytical results. The symbolic computation capabilities of
Mathematica are indeed a significant advantage when working with neural networks and deep learning.
This feature allows users to handle mathematical expressions symbolically, enabling them to perform
tasks such as analytical derivations, evaluating complex integrals, and solving differential equations that
involve their models. By integrating symbolic computation with neural network modeling, Mathematica
provides a platform where users can conduct theoretical work with enhanced precision and rigor. This
integration not only streamlines the workflow but also ensures that the analyses are more thorough and
accurate, making Mathematica an excellent choice for those who require both computational power and
mathematical insight in their neural network and deep learning projects.
• Comprehensive Built-in Functions: Mathematica provides a vast library of built-in functions for neural
networks and deep learning, including functions for defining layers, loss functions, optimizers, and
regularization techniques. These functions are highly optimized, ensuring efficient computation without
the need for extensive manual coding. Additionally, Mathematica's high-level abstractions simplify the
construction and training of neural networks, making it accessible even to those with limited
programming experience.
• Integration with Other Mathematica Features: Neural networks in Mathematica can be easily integrated
with its extensive suite of tools for data visualization, symbolic computation, image processing, and
statistical analysis. This integration allows users to preprocess data, visualize model performance, and
analyze results within a single environment, streamlining the workflow and enhancing productivity.
• Automatic Differentiation and Optimization: Mathematica supports automatic differentiation, which is
crucial for training neural networks, as it simplifies the computation of gradients required for
optimization. Combined with its powerful optimization algorithms, Mathematica enables efficient
training of complex models, even when the underlying mathematical expressions are highly sophisticated.
• Flexibility and Extensibility: Mathematica offers a high degree of flexibility in model construction,
allowing users to define custom layers, activation functions, and loss functions. This is particularly
advantageous for researchers experimenting with novel architectures or those working on specialized
applications. Furthermore, Mathematica's programming language, Wolfram Language, is highly
extensible, allowing users to incorporate external libraries or frameworks if needed.
• Interactive Notebooks: Mathematica's notebook interface provides an interactive environment where
users can write code, run simulations, visualize results, and document their work all in one place. This is
especially useful for educational purposes, presentations, and collaborative research, as it allows for a
clear and coherent presentation of ideas, code, and results.
v
FRONTMATTER
By choosing Mathematica for neural networks and deep learning, users gain access to a powerful, flexible, and
integrated environment that supports the entire lifecycle of model development—from theory and experimentation to
deployment and analysis. This makes Mathematica an excellent choice for researchers, educators, and practitioners
alike.
Throughout this book, we delve into a wide range of topics, from fundamental principles to advanced techniques,
always with an emphasis on overcoming the specific hurdles that practitioners encounter. We explore essential
concepts such as model generalization, regularization, and optimization, while also addressing cutting-edge topics like
complex-valued neural networks, advanced activation functions, and automated hyperparameter tuning.
This book is designed not only to cater to beginners in the field but also to serve as a valuable reference for seasoned
data scientists, machine learning practitioners, biostatisticians, finance professionals, and engineers. Whether they
possess prior knowledge of deep learning or seek to fill gaps in their understanding, this book aims to address their
needs. We assume that the reader has no prior experience in neural networks and optimization.
Each chapter is designed to build on the previous ones, creating a cohesive and comprehensive guide to artificial
neural networks and deep learning. Whether you are a student, researcher, or practitioner, this book will equip you
with the knowledge and skills to tackle the challenges of modern artificial intelligence and contribute to the ongoing
advancements in this exciting field.
In the first chapter, we begin by laying the foundation. This chapter is an essential primer that introduces the basic
concepts, functions, and tools of Mathematica. From arithmetic operations and algebraic manipulations to advanced
graphing and functional programming, you will gain a solid understanding of how to utilize Mathematica's capabilities
to perform a wide range of computations and visualizations. The chapter also covers the construction of modular and
reusable code, which is crucial for developing efficient and scalable neural network models.
As you progress through the book, you will encounter increasingly sophisticated topics, each building on the
knowledge gained in the previous chapters. You will explore descriptive statistics and probability theory, which are
foundational to understanding data distribution and preparing data for machine learning tasks. The book will guide
you through matrix calculus and gradient optimization, providing the mathematical tools needed for model training
and fine-tuning.
vi
FRONTMATTER
One of the key strengths of Mathematica is its ability to seamlessly integrate symbolic computation with practical
implementation. This is particularly evident in the chapters dedicated to constructing and optimizing multilayer feed-
forward neural networks, where you will learn not only the theoretical aspects of neural networks but also how to
implement them efficiently using Mathematica’s powerful functions like NetChain, NetGraph, and NetTrain.
As neural networks grow in complexity, so do the challenges associated with their optimization. This book
dedicates an entire chapter to addressing these challenges, offering strategies for monitoring training progress,
mitigating issues such as vanishing gradients, and improving model generalization through advanced regularization
techniques. You will also explore adaptive learning rate schedules and gradient descent variants, which are critical for
fine-tuning your models and achieving optimal performance.
The book concludes with a deep dive into advanced activation functions and complex-valued neural networks,
topics that are at the forefront of current research in deep learning. Here, Mathematica’s symbolic and visualization
capabilities truly shine, allowing you to explore and understand the behavior of these advanced functions in both two-
dimensional and three-dimensional spaces.
Throughout "Neural Network and Deep Learning with Mathematica", you will find detailed explanations, practical
examples, and Mathematica code snippets that ensure a hands-on learning experience. By the end of this book, you
will be equipped with both the theoretical knowledge and practical skills to tackle complex neural network challenges,
making full use of Mathematica’s unique computational capabilities.
Finally, we extend our heartfelt thanks to Professor Mohamed Abdalla Darwish, Head of the Department of
Mathematics and Computer Science, Faculty of Science, Damanhour University, Egypt, for his unwavering support.
We are profoundly grateful to Professor Amr R. El Dhaba for his invaluable discussions and continued encouragement.
We also wish to express our sincere appreciation to our colleagues and friends for their invaluable feedback,
thoughtful comments, and constructive suggestions. In particular, we would like to acknowledge Professor Hamed
Awad, Dr. Fatma El-Safty, Dr. Hamdy El Shamy, Dr. Mohamed Elhaddad, Mohamed Yahia, Ayman A. Abdelaziz,
Eman Farag, Hassan M. Shetawy, Walaa Mansour, Moaz El-Essawey, Aziza Salah, and Eman R. Hendawy for their
contributions.
We hope that you find this book informative and inspiring, and that it serves as a valuable resource in your journey
through the world of artificial neural networks and deep learning.
vii
FRONTMATTER
However, attempting to cover both the theoretical concepts and computational algorithms exhaustively within a
single volume would be impractical. To ensure a thorough exploration of both aspects, this book is divided into two
complementary parts. The first part is titled "Artificial Neural Network and Deep Learning: Fundamentals and
Theory." The second part is titled " Neural Network and Deep Learning with Mathematica" For each theoretical
chapter in the first part, there is a corresponding chapter in the second part. We strongly recommend that after
completing each theoretical chapter, you explore the corresponding practical implementation chapter in the
complementary volume. This dual approach will provide you with a well-rounded understanding and the skills
necessary to excel in this field.
The book "Neural Network and Deep Learning with Mathematica" adopts a refreshingly code-centric approach,
enabling you to solidify your understanding through hands-on practice. Nearly all the concepts introduced are
accompanied by illustrative code examples, making the learning experience both practical and tangible. Even the
figures in the first part are generated using these code examples, emphasizing the code-first methodology. To ensure
accessibility and ease of understanding, the code examples are deliberately crafted in a simple format, prioritizing
readability over efficiency and generality. In line with our instructional philosophy, each code example serves a dual
purpose: not only does it demonstrate a specific deep learning concept, but it also simultaneously introduces and
reinforces Mathematica programming techniques. Readers will learn how to leverage Mathematica to perform
complex neural network and deep learning calculations, simulate data, and create visual representations of their
findings.
viii
FRONTMATTER
CONTENTS
Unit 4.1. Building Neural Network from Scratch with Mathematica and Universal Approximation 135
Theorem
Unit 4.2. Layers: LinearLayer and ElementwiseLayer 160
Unit 4.3. Containers: NetChain and NetGraph 174
Unit 4.4. NetInitialize 190
Unit 4.5. Cost Functions 197
Unit 4.6. NetTrain 206
Unit 6.1. Understanding Learning Rate Schedules and Adaptive Algorithms with Mathematica 300
Unit 6.2. Optimizing Neural Networks with Learning Rate Schedules and Adaptive Algorithms in 339
Mathematica
Unit 7.1. The Fundamentals of Overfitting: What It Is and Why It Happens 358
Unit 7.2. Performance Metrics 367
Unit 7.3. Gaussian Processes Implementation in Mathematica from Scratch 383
Unit 7.4. Setting up Bayesian Optimization in Mathematica 402
Unit 7.5. Automated Hyperparameter Tuning with Mathematica 420
ix
FRONTMATTER
x
FRONTMATTER
xi
CHAPTER 1 INTRODUCTION TO MATHEMATICA
CHAPTER 1
INTRODUCTION TO MATHEMATICA
Mathematica is a powerful computational software program widely used in various fields of science, engineering, and
mathematics. It provides a comprehensive environment for performing symbolic and numeric computations, creating
visualizations, and solving complex problems. In this introductory chapter, we have covered the basic concepts and
functions of Mathematica, including the following topics.
• Basic Concepts: Mathematica is built on a foundation of mathematical and computational concepts. It allows
you to perform arithmetic operations, manipulate mathematical expressions, and solve equations. The
software provides a vast collection of built-in functions for numerical calculations, algebraic manipulations,
calculus, linear algebra, and more. These functions serve as fundamental tools for performing various tasks
in Mathematica.
• Variables and Functions: In Mathematica, variables are used to store values that can be accessed and
manipulated throughout a computation. You can assign values to variables using the assignment operator
(:=) or the equal sign (=). Functions, on the other hand, are defined using the syntax:
functionName[arguments]:= functionBody. Functions encapsulate a series of instructions that can be reused
and called with different arguments.
• Lists: Lists are an essential data structure in Mathematica. They allow you to store collections of values, such
as numbers, strings, or even other lists. Lists can be created using curly braces ( {}) and elements are separated
by commas. Mathematica provides a rich set of built-in functions for manipulating and operating on lists,
including appending, deleting, sorting, and extracting elements.
• 2D and 3D Graphing: Mathematica offers powerful graphing capabilities for visualizing mathematical
functions and data in two or three dimensions. You can plot functions using the Plot and ParametricPlot
functions for 2D graphs, and Plot3D and ParametricPlot3D functions for 3D graphs. These functions allow
you to customize various aspects of the plots, such as axes labels, plot ranges, colors, and styles.
• Control Structures: Control structures in Mathematica enable you to control the flow of execution in your
programs. They include conditionals (If, Switch), loops (For, While), and functional programming
constructs (Map, Fold, Nest). These control structures allow you to make decisions, iterate over lists or ranges
of values, and perform operations on collections of data.
• Modules, Blocks, and Local Variables: Mathematica provides mechanisms for creating modular and reusable
code through modules and blocks. Modules allow you to encapsulate a group of variables and functions,
providing a local scope for their usage. Blocks are similar but are primarily used for scoping variables and
expressions dynamically. Local variables defined within modules or blocks are not visible outside their scope,
ensuring better code organization and reducing potential conflicts.
• Functional Programming: Functional programming leverages its symbolic foundation to provide a uniquely
powerful approach to problem-solving. The integration of symbolic data and functions, combined with
pattern matching and rule-based programming, enables concise and expressive code for applications.
1
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Unit 1.1
Basic Concepts
Mathematica is a computer algebra system that performs numeric, symbolic, and graphical computations. Although
Mathematica can be used as a programming language, its high-level structure is more appropriate for performing
sophisticated operations through the use of built-in functions. For example, Mathematica can find limits, derivatives,
integrals, and determinants, as well as plot the graph of functions and perform symbolic computations. The number
of built-in functions in Mathematica is enormous. Our goals in this introductory chapter are modest. Namely, we
introduce a small subset of Mathematica commands necessary to explore Mathematica discussed in this book.
Notebooks
A notebook is a document that allows us to interact with Mathematica. Each notebook is divided up into a sequence
of individual units called cells, each containing a specific type of information such as text, graphics, input, or output.
Text cells contain information to be read by the user but contain no executable Mathematica commands. The following
cell, displaying In[1] 220, is an example of an input cell containing executable Mathematica commands. Mathematica
computes the value of 220 and the results of the calculation are displayed as Out[1]:1048576 in an output cell. When
we create a new cell, the default cell type is an input cell. Suppose instead, we want to create a text cell. To do this,
use the mouse to click on an area where we want to create a new cell and a horizontal line will appear. Then from the
Format menu, select Style and then Text. A new text cell will then be created as soon as we begin typing. We can
experiment with creating other types of cells by selecting a cell style of our choice, after first choosing Format and
Style from the menu.
Palettes
A palette is similar to a set of calculator buttons, providing shortcuts to entering commands and symbols into a
notebook. The name of a useful palette is “Basic Math Assistant Input” and it can be found by selecting the Palettes
menu and then Basic Math Assistant. After opening Basic Math Assistant, drag it to the right side of the screen and
resize the notebook, if necessary, so that both the notebook and palette are visible in non-overlapping windows. To
demonstrate the usefulness of palettes, suppose we wish to calculate √804609. The Mathematica command for
computing the square root of n is Sqrt[n]. The following input cell was created by typing in the information
exclusively from the keyboard.
Input Sqrt[804609]
Output 897
A quicker and more natural way of entering √804609 can be accomplished by clicking on the square root button √□
in the palette and then entering 804609.
Input √(804609)
Output 897
Packages
Note that, many of Mathematica functions are available at startup, but additional specialized functions are available
from add-in packages. You can load a built-in or installed package in two ways, with the Needs[ ] function or with
the symbols <<. The package name has quotation marks if you use the Needs[ ] function, but does not has a mark
with <<. Package names are always indicated with a backward apostrophe at the end of the name, `.
Input Needs["PackageName`"]
Input <<PackageName`
2
CHAPTER 1 INTRODUCTION TO MATHEMATICA
There are four important tricks to keep in mind to help with Mathematica:
1- If you want to know something about a Mathematica function or procedure, just type ? followed by a
Mathematica command name, and then enter the cell to get information on that command.
Input ?FactorInteger
After you press Enter, Mathematica responds:
Output FactorInteger[n] gives a list of the prime factors of the integer n, together
with their exponents.
2- Mathematica also can finish typing a command for you if you provide the first few letters. Here is how it works:
After typing a few letters choose Complete Selection from the Edit menu. If more than one completion is
possible, you will be presented with a pop-up menu containing all of the options. Just click on the appropriate
choice.
3- If you know the name of a command but have forgotten the syntax for its arguments, type the command name
in an input cell, then choose Make Template from the Edit menu. Mathematica will paste a template into the
input cell showing the syntax for the simplest form of the command. For example, if you typed Plot, and then
choose Make Template, the input cell would look like this:
Input Plot[f,{x,xmin, xmax}]
4- The Wolfram Documentation is the most useful feature imaginable; learn to use it and use it often. Go to the
Help menu and choose Wolfram Documentation. A window will appear displaying the documentation home
page.
When you write programs in the Wolfram Language, there are various ways to document your code. As always,
by far the best thing is to write clear code and to name the objects you define as explicitly as possible. Sometimes,
however, you may want to add some "commentary text" to your code, to make it easier to understand. You can add
such text at any point in your code simply by enclosing it in matching (* *). Notice that in the Wolfram Language,
"comments" enclosed in (* *) can be nested in any way.
Arithmetic Operations
Mathematica can be thought of as a sophisticated calculator, able to perform exact as well as approximate arithmetic
computations. You can always control grouping the arithmetic computations by explicitly using parentheses. The
following list summarizes the Mathematica symbols used for addition, subtraction, multiplication, division, and
powers.
3
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Output 7.93
Input 2.4/8.9^2
Output 0.0302992
Input 2*3*4
Output 24
Input (3+4)^2-2(3+1)
Output 41
The precedence of common operators is generally defined so that "higher-level" operations are performed first. For
simple expressions, operations are typically ordered from highest to lowest in order: 1. Parenthesization, 2. Factorial,
3. Exponentiation, 4. Multiplication and division, 5. Addition and subtraction. Consider the expression 3×7+2^2. This
expression has a value (3×7)+(2^2)=25.
Mathematica has several built-in constants. The three most commonly used constants are π, e, and i. You can find
each of these constants on the Basic Math Assistant palette. Some built-in constants are listed below.
I (𝑖 = √(−1)).
E (2.71828).
Pi (𝜋 = 3.14159).
Relational and logical operators are instrumental in program flow control. They are used in Mathematica to test various
conditions involving variables and expressions. The relational operators are listed below.
Logical operators are used to negate or combine relational expressions. The standard logical operators are listed below.
e₁&&e₂&&... is the logical AND function. It evaluates its arguments in order, giving False immediately if any
of them are False, and True if they are all True.
e₁||e₂||... is the logical OR function. It evaluates its arguments in order, giving True immediately if any of
them are True, and False if they are all False.
!expr is the logical NOT function. It gives False if expr is True, and True if it is False.
Input Pi^E<E^Pi
Output True
Input 2+2==4
Output True
4
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Output x^2==1+x
Input (* Returns True if elements are guaranteed unequal, and otherwise stays unevaluated:
*)
a!=b
Output a!=b
Input 1!=2
Output True
Input 1>2||Pi>3
Output True
Input 2>1&&Pi>3
Output True
Input (3<5)||(4<5)
Output True
Input (3<5)&&!(4>5)
Output True
Elementary Functions
In the following, we discuss some of the more commonly used functions Mathematica offers. The Wolfram Language
has nearly 6000 built-in functions. All have names in which each word starts with a capital letter. Remember that the
argument of a function must be contained within square brackets, [ ]. Arguments to functions are always separated
by commas.
Common Functions
Trigonometric Functions
Hyperbolic Functions
Numerical Functions
5
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Combinatorial Functions
Input Sin[Pi/3]
Output Sqrt[3]/2
Input Sinh[1.4]
Output 1.9043
Input N[1/7]
Output 0.142857
Input Floor[2.4]
Output 2
Input 30!
Output 265252859812191058636308480000000
Input Binomial[n,2]
Output 1/2 (-1+n) n
Input Multinomial[6,5]
Output 462
Sums and products are of fundamental importance in mathematics, and Mathematica makes their computation simple.
Unlike other computer languages, initialization is automatic and the syntax is easy to apply, particularly if the Basic
Math Assistant Input palette is used. Any symbol may be used as the index of summation. Negative increments are
permitted wherever an increment is used.
Sum[f,{i,imax}] i
max
evaluates the ∑i=1 f.
Sum[f,{i,imin,imax}] starts with i = imin .
Sum[f,{i,imin,imax,di}] uses steps di.
Sum[f,{i,{i₁,i₂,…}}] uses successive values i₁, i₂, ….
Sum[f,{i,imin,imax},{j,jmin,jmax},…] imax jmax
evaluates the multiple sum ∑i=1 ∑j=1 f.
6
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Product[f,{i,imax}] imax
evaluates the ∏i=1 f.
Product[f,{i,imin,imax}] starts with i = imin .
Product[f,{i,imin,imax,di}] uses steps di.
Product[f,{i,{i₁,i₂,…}}] uses successive values i₁, i₂, ….
Product[f,{i,imin,imax},{j,jmin,jmax},…] imax jmax
evaluates the multiple sum ∏i=1 ∏j=1 f.
Input Sum[1/i^6,{i,1,Infinity}]
Output π^6/945
Input Product[i^2,{i,1,6}]
Output 518400
Input Product[i^2,{i,1,n}]
Output (n!)^2
Input Product[2^(j+i),{i,1,p},{j,1,i}]
Output 2^(1/2 p (1 + p)^2)
Input Limit[(1+x/n)^n,n->Infinity]
Output E^x
Input Series[x^x,{x,0,4}]
Output 1 + Log[x] x + 1/2 Log[x]^2 x^2 + 1/6 Log[x]^3 x^3 + 1/24 Log[x]^4 x^4 + O[x]^5
Differentiation Function
7
CHAPTER 1 INTRODUCTION TO MATHEMATICA
D[f,x] ∂
gives the partial derivative f.
∂x
D[f,x,y,...] ∂ ∂
gives the derivative … f.
∂x ∂y
D[f,{x,n}] ∂n
gives the multiple derivative f.
∂xn
Input D[ArcCoth[x],{x,2}]
Output (2 x)/(1 - x^2)^2
Integration Functions
Input \[Integral]Sqrt[x+Sqrt[x]]\[DifferentialD]x
Output 1/12 Sqrt[Sqrt[x] + x] (-3 + 2 Sqrt[x] + 8 x) + 1/4 ArcTanh[Sqrt[Sqrt[x] +
x]/Sqrt[x]]
Input Integrate[1/((x^4+x^2+1)),{x,0,Infinity}]
Output \[Pi]/(2 Sqrt[3])
Input Integrate[x^2+y^2,{x,0,1},{y,0,x}]
Output 1/3
8
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Algebraic Operations
Mathematica has many functions for transforming algebraic expressions. The following list summarizes them.
Simplify[expr] performs a sequence of algebraic and other transformations on expr and returns the
simplest form it finds.
Expand[expr] expands out products and positive integer powers in expr.
Factor[expr] factors a polynomial over the integers.
Together[expr] puts terms in a sum over a common denominator, and cancels factors in the result.
ExpandAll[expr] expands out all products and integer powers in any part of expr.
FunctionExpand[expr] tries to expand out special and certain other functions in expr when possible reducing
compound arguments to simpler ones.
Reduce[expr,vars] reduces the statement expr by solving equations or inequalities for vars and
eliminating quantifiers.
Input Expand[(1+x)^10]
Output 1 + 10 x + 45 x^2 + 120 x^3 + 210 x^4 + 252 x^5 + 210 x^6 + 120 x^7 + 45 x^8
+ 10 x^9 + x^10
Input Factor[x^10-1]
Output (-1 + x) (1 + x) (1 - x + x^2 - x^3 + x^4) (1 + x + x^2 + x^3 + x^4)
Input Together[x^2/(x^2-1)+x/(x^2-1)]
Output x/(-1+x)
Solving Equations
Solutions of general algebraic equations may be found using the Solve command. Solve always tries to give you
explicit formulas for the solutions to equations. However, it is a basic mathematical result that, for sufficiently
complicated equations, explicit algebraic formulas in terms of radicals cannot be given. If you have an algebraic
equation in one variable, and the highest power of the variable is at most four, then the Wolfram Language can always
give you formulas for the solutions. However, if the highest power is five or more, it may be mathematically
impossible to give explicit algebraic formulas for all the solutions.
You can also use the Wolfram Language to solve sets of simultaneous equations. You simply give the list of
equations and specify the list of variables to solve for. Not all algebraic equations are solvable by Mathematica, even
if theoretical solutions exist. If Mathematica is unable to solve an equation, it will represent the solution in a symbolic
form. For the most part, such solutions are useless, and a numerical approximation is more appropriate. Numerical
approximations are obtained with the command NSolve.
9
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input Reduce[x^2-y^3==1,{x,y}]
Output y == (-1 + x^2)^(1/3) || y == -(-1)^(1/3) (-1 + x^2)^(1/3) || y == (-1)^(2/3)
(-1 + x^2)^(1/3)
Input FindRoot[Sin[x]+Exp[x],{x,0}]
Output {x->-0.588533}
Some Notes
1- In doing calculations, you will often need to use previous results that you have got. In the Wolfram Language,
% always stands for your last result.
Input %+1
Output 5930
Input 3 %+%^2+%%
Output 35188619
Input % 2+% 3
Output 175943095
2- Although Mathematica is a powerful calculating tool, it has its limits. Sometimes it will happen that the
calculations you tell Mathematica to do are too complicated or may be the output produced is too long. In these cases,
Mathematica could be calculating for too long to get an output so you might want to stop these calculations. To abort
a calculation: go to "Kernel" and select "Abort evaluation". It can take long to abort a calculation. If the computer
does not respond an alternative is to close down the Kernel. By doing this you do not lose the data displayed in your
notebooks, but you do lose all the results obtained so far from the Kernel, so in case you are running a series of
10
CHAPTER 1 INTRODUCTION TO MATHEMATICA
calculations, you would have to start again. To close down the Kernel: go to "Kernel" and select "Quit Kernel" and
then "Local". Closing down the Kernel is not a practice that is done only when you want to stop a calculation.
Sometimes, when you have been using Mathematica for a long time you forget about the definitions and calculations
that you have done before (you might have defined values for variables or functions, for example). Those definitions
can clash with the calculations you are doing, so you might want to close down the Kernel and start your new
calculations from scratch. In general, it is a good idea to close down the Kernel after you have finished with a series
of calculations so that when you move to a different problem your new calculations do not interact with the previous
ones.
11
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Unit 1.2
Variables and Functions
When you perform long calculations, it is often convenient to give names to your intermediate results. Just as in
standard mathematics, or other computer languages, you can do this by introducing named variables. It is very
important to realize that the values you assign to variables are permanent. Once you have assigned a value to a
particular variable, the value will be kept until you explicitly remove it. The value will, of course, disappear if you
start a whole new Wolfram Language session.
Input x^2
Output 25
Input x=7+4
Output 11
In Mathematica, one can substitute an expression with another using rules. In particular one can substitute a variable
with a value without assigning the value to the variable.
lhs:=rhs assigns rhs to be the delayed value of lhs. rhs is maintained in an unevaluated form.
When lhs appears, it is replaced by rhs, evaluated afresh each time.
expr/.rules applies a rule or list of rules in an attempt to transform each subpart of an expression
expr.
lhs->rhs or lhs->rhs represents a rule that transforms lhs to rhs.
Input x=10
Output 10
Input y
Output 12
12
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input x^2+y/.x->y/.y->x
Output x + x^2
The last example reveals that Mathematica goes through the expression only once and replaces the rules. If we need
Mathematica to go through the expression again and replace any expression which is possible until no substitution is
possible, one uses //. . In fact /. and //. are shorthand for Replace and ReplaceRepeated, respectively.
There are many functions that are built into the Wolfram Language. Here we discuss how you can add your own
simple functions to the Wolfram Language. As a first example, consider adding a function called f which squares its
argument. The Wolfram Language command to define this function is f[x]:=x^2. The names like f that you use for
functions in the Wolfram Language are just symbols. Because of this, you should make sure to avoid using names
that begin with capital letters, to prevent confusion with built-in Wolfram Language functions. You should also
make sure that you have not used the names for anything else earlier in your session.
Input f[4]
Output 16
13
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input Expand[f[(x+1+y)]]
Output 1+2 x+x^2+2 y+2 x y+y^2
Input Function[u,3+u][x]
Output 3+x
Input Function[{u,v},u^2+v^4][x,y]
Output x^2+y^4
Input f/@{a,b,c,d,e}
Output {f[a],f[b],f[c],f[d],f[e]}
One can define functions of several variables. Here is a simple example defining 𝑓(𝑥, 𝑦) = √𝑥 2 + 𝑦 2 .
Output 5
Some Notes
1- There are four kinds of bracketing used in the Wolfram Language. Each kind of bracketing has a very
different meaning.
expr₁;expr₂;expr₃ do several operations and give the result of the last one.
expr₁;expr₂; do the operations but print no output.
expr; do an operation but display no output.
Input a=2;b=3;a+b
Output 5
14
CHAPTER 1 INTRODUCTION TO MATHEMATICA
3- Particularly when you write procedural programs in the Wolfram Language, you will often need to modify
the value of a particular variable repeatedly. You can always do this by constructing the new value and
explicitly performing an assignment such as x=value. The Wolfram Language, however, provides special
notations for incrementing the values of variables, and for some other common cases.
Input k
Output 2
Input k=x
Output x
Input k++
Output x
Input k
Output 1+x
Input k=1;++k
Output 2
Input k
Output 2
Input k=1;k--
Output 1
Input k
Output 0
Input k=1;k-=5
Output -4
Input k
Output -4
4- Primarily there are three equalities in Mathematica, =, :=, ==. There is a fundamental differences between =
and := explained in the following examples:
15
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input y Input y
Output 7 Output 12
Input y Input y
Output 7 Output 17
It is clear that when we defined y=x+2 then y takes the value of x+2 and this will be assigned to y. No matter if x
changes its value, the value of y remains the same. In other words, y is independent of x. But in y:=x+2, y is dependent
on x, and when x changes, the value of y changes too. Namely using := then y is a function with variable x. Finally,
the equality == is used to compare:
Input 3==5
Output False
16
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Unit 1.3
Lists
Lists are extremely important objects. In doing calculations, it is often convenient to collect together several objects
and treat them as a single entity. Lists give you a way to make collections of objects. Lists are sequences of
Mathematica objects separated by commas and enclosed by curly brackets. A list such as {3,5,1} is a collection of
three objects. But in many ways, you can treat the whole list as a single object. You can, for example, do arithmetic
on the whole list at once, or assign the whole list to be the value of a variable.
Defining your own lists is easy. You can, for example, type them in full, like this:
Input oddList = {81, 3, 5, 7, 9, 11, 13, 15, 17}
Output {81, 3, 5, 7, 9, 11, 13, 15, 17}
Alternatively, if (as here) the list elements correspond to a rule of some kind, the command Table can be used, like
this:
Input oddList = Table[2 n + 1, {n, 0, 8}]
Output {1, 3, 5, 7, 9, 11, 13, 15, 17}
The functions for obtaining elements of lists are
Input First[{{a,b},{c,d}}]
Output {a,b}
Input Last[{a,b,c}]
Output c
Input {a,b,c,d,e,f}[[3]]
Output c
Input {{a,b,c},{d,e,f},{g,h,i}}[[2,3]]
Output f
Input Take[{a,b,c,d,e,f},4]
Output {a,b,c,d}
17
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input Rest[{a,b,c,d}]
Output {b,c,d}
Input Most[{a,b,c,d}]
Output {a,b,c}
Input Drop[{a,b,c,d,e,f},2]
Output {c,d,e,f}
Some functions for inserting, deleting, and replacing list and sublist elements are
Input Append[{a,b,c,d},x]
Output {a,b,c,d,x}
Input Insert[{a,b,c,d,e},x,3]
Output {a,b,x,c,d,e}
Input Insert[{a,b,c,d,e},x,-2]
Output {a,b,c,d,x,e}
Input Delete[{a,b,c,d},3]
Output {a,b,d}
Input Delete[{a,b,c,d},{{1},{3}}]
Output {b,d}
Input ReplacePart[{a,b,c,d,e},3->xxx]
Output {a,b,xxx,d,e}
Input ReplacePart[{a,b,c,d,e},{2->xx,5->yy}]
Output {a,xx,c,d,yy}
18
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input Sort[{4,1,3,2,2},Greater]
Output {4,3,2,2,1}
Input Union[{1,2,1,3,6,2,2}]
Output {1,2,3,6}
Input Union[{a,b,a,c},{d,a,e,b},{c,a}]
Output {a,b,c,d,e}
Input Reverse[{a,b,c,d}]
Output {d,c,b,a}
Input RotateLeft[{a,b,c,d,e},2]
Output {c,d,e,a,b}
Input RotateRight[{a,b,c,d,e},2]
Output {d,e,a,b,c}
Input Permutations[{a,b,c}]
Output {{a,b,c},{a,c,b},{b,a,c},{b,c,a},{c,a,b},{c,b,a}}
Input Partition[{a,b,c,d,e,f},2]
Output {{a,b},{c,d},{e,f}}
Input Flatten[{{a,b},{c,{d},e},{f,{g,h}}}]
Output {a,b,c,d,e,f,g,h}
Input Transpose[{{a,b,c},{x,y,z}}]
Output {{a,x},{b,y},{c,z}}
Input Join[{a,b,c},{x,y},{u,v,w}]
Output {a,b,c,x,y,u,v,w}
19
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Vectors and matrices in the Wolfram Language are simply represented by lists and by lists of lists, respectively.
Functions for generating lists are Range[ ], Table[ ], and Array[ ].
Vectors
Mathematica has many functions for generating vectors. The following list summarizes them.
Input v={x,y}
Output {x,y}
Input Range[4]
Output {1,2,3,4}
Input Range[x,x+4]
Output {x,1+x,2+x,3+x,4+x}
Input Table[i^2,{i,10}]
Output {1,4,9,16,25,36,49,64,81,100}
Input Length[{a,b,c,d}]
Output 4
Input {5,8,6,9}[[2]]
Output 8
Input Cross[{a,b,c},{x,y,z}]
Output {-c y+b z,c x-a z,-b x+a y}
Input Norm[{x,y,z}]
Output Sqrt[Abs[x]^2 + Abs[y]^2 + Abs[z]^2]
Input Normalize[{1,5,1}]
Output {1/(3 Sqrt[3]), 5/(3 Sqrt[3]), 1/(3 Sqrt[3])}
20
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input Orthogonalize[{{1,0,1},{1,1,1}}]
Output {1/Sqrt[2], 0, 1/Sqrt[2]}, {0, 1, 0}}
Matrix
Mathematica has many functions for generating matrices. The following list summarizes them.
{{a,b},{c,d}} a b
matrix ( ).
c d
Table[f,{i,m},{j,n}] build an m × n matrix by evaluating f with i ranging from 1 to m and j
ranging.
List[[i,j]] or Part[list,i,j] give the i, j th element in the matrix list.
DiagonalMatrix[list] generate a square matrix with the elements in list on the main.
Dimensions[list] give the dimensions of a matrix represented by list.
Column[list] display the elements of list in a column.
c m multiply a matrix m by a scalar.
a.b dot product of two matrices a. b.
Inverse[m] matrix inverse m.
MatrixPower[m,n] gives the nth power of a matrix m.
Det[m] Determinant m.
Tr[m] Trace m.
Transpose[m] Transpose m.
Input m[[1]]
Output {a,b}
Input m[[1,2]]
Output b
Input v={x,y}
Output {x,y}
Input m.v
Output {a x+b y,c x+d y}
Input m.m
Output {{a^2+b c,a b+b d},{a c+c d,b c+d^2}}
Input s=Table[i+j,{i,3},{j,3}]
Output {{2,3,4},{3,4,5},{4,5,6}}
Input DiagonalMatrix[{a,b,c}]
Output {{a,0,0},{0,b,0},{0,0,c}}
Input Det[m]
Output -b c+a d
Input Transpose[m]
Output {{a,c},{b,d}}
Input h=Table[1/(i+j-1),{i,3},{j,3}]
Output {{1,1/2,1/3},{1/2,1/3,1/4},{1/3,1/4,1/5}}
21
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input Inverse[h]
Output {{9,-36,30},{-36,192,-180},{30,-180,180}}
Array
Input Array[f,{3,2}]
Output {{f[1,1],f[1,2]},{f[2,1],f[2,2]},{f[3,1],f[3,2]}}
Input MatrixForm[Table[1/(i+j),{i,4},{j,4}]]
Output 1/2 1/3 1/4 1/5
1/3 1/4 1/5 1/6
( )
1/4 1/5 1/6 1/7
1/5 1/6 1/7 1/8
Input TableForm[Table[1/(i+j),{i,4},{j,4}]]
Output 1/2 1/3 1/4 1/5
1/3 1/4 1/5 1/6
1/4 1/5 1/6 1/7
1/5 1/6 1/7 1/8
Input Grid[{{a,b,c},{x,y,z}}]
Output a b c
x y z
22
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input Grid[{{a,b,c},{x,y^2,z^3}},Frame->All]
Output a b c
x y^2 z^3
Input Row[{aaa,b,cccc}]
Output aaabcccc
Input Row[{aaa,b,cccc},"----"]
Output aaa----b----cccc
Input Column[{1,12,123,1234}]
Output 1
12
123
1234
Input Column[{1,22,333,4444},Frame->True]
Output 1
22
333
4444
Input Multicolumn[Range[50],{6,Automatic}]
Output 1 7 13 19 25 31 37 43 49
2 8 14 20 26 32 38 44 50
3 9 15 21 27 33 39 45
4 10 16 22 28 34 40 46
5 11 17 23 29 35 41 47
6 12 18 24 30 36 42 48
Notes:
1- When using MatrixForm, it is very important to note that the MatrixForm is used for display purposes only. If a
matrix is defined with the MatrixForm in it, that matrix definition cannot be used in any subsequent calculation. For
example, consider the following definition of matrix m:
Input: m = MatrixForm[{{1, 2, 3,4}, {5, 6, 7,8}, {9,10,11,12}}]
Output:
({
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
})
We cannot perform any operations on matrix m in this form. For example, using the Transpose function on m simply
returns the initial matrix m wrapped in Transpose.
Input: Transpose[m]
Output:
Transpose[
({
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
})]
23
CHAPTER 1 INTRODUCTION TO MATHEMATICA
The solution obviously is not to use the MatrixForm in the definition of matrices. After the definition, we can use
the MatrixForm to get a nice-looking display.
Input: m={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; MatrixForm[m]
Output:
({
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
})
Input: Transpose[m]
Output: {{1,5,9},{2,6,10},{3,7,11},{4,8,12}}
2- To explicitly define a 3 × 1 column vector is to enter it as a two-dimensional list. Here, each entry defines a row
of a matrix with one column.
Input: a={{1},{2},{3}};MatrixForm[a]
Output:
({
{1},
{2},
{3}
})
Input: b={4,5,6}
Output: {4,5,6}
In this case Transpose[a] . b makes sense. However, the result is a 1 × 1 matrix and not a scalar.
Input: Transpose[a].b
Output: {32}
Obviously, now a . b will produce an error because the dimensions do not match.
Input: a.b
Output:
{{1},{2},{3}}.{4,5,6}
To get a 3 × 3 matrix, we need to define b as a two-dimensional matrix with only one row, as follows:
Input: b={{4,5,6}}
Output: {{4,5,6}}
({
{4, 5, 6},
{8, 10, 12},
{12, 15, 18}
})
24
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input v={{x,y}};
MatrixForm[v]
MatrixForm[Transpose[v]]
Output ({
{x, y}
})
Output ({
{x},
{y}
})
25
CHAPTER 1 INTRODUCTION TO MATHEMATICA
{ , }
3- Since Mathematica treats matrices as essentially lists, it does not distinguish between a column or a row vector.
The actual form is determined from syntax in which it is used. For example, define two vectors a and b as follows:
Input : a={1, 2, 3}; b={4, 5, 6};
The inner product is evaluated simply as a . b, resulting in a scalar. Explicitly evaluating Transpose[a]. b will
produce the same result.
Input : a . b
Output: 32
Input : Transpose[a] . b
Output: 32
If we want to treat a as a column vector (3 × 1) and b as a row vector (1 × 3) to get a 3 × 3 matrix from the product,
we need to use the Outer function of Mathematica, as follows:
Input : ab = Outer[Times, a, b]; MatrixForm[ab]
Output :
({
{4, 5, 6},
{8, 10, 12},
{12, 15, 18}
})
26
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input (* Dot effectively treats vectors multiplied from the left as row vectors: *)
{1, 1, 1} . a
Output {9, 12}
Gradient function
𝜕𝑓 𝜕𝑓
Grad[f,{x1,…,xn}] gives the gradient ( ,…, ).
𝜕𝑥1 𝜕𝑥𝑛
Input (* The gradient of a vector field in Cartesian coordinates, the Jacobian matrix:
*)
Grad[{f[x, y, z], g[x, y, z], h[x, y, z]}, {x, y, z}] // MatrixForm
Output ({
{f(1,0,0)[x,y,z], f(0,1,0)[x,y,z], f(0,0,1)[x,y,z]},
{g(1,0,0)[x,y,z], g(0,1,0)[x,y,z], g(0,0,1)[x,y,z]},
{h(1,0,0)[x,y,z], h(0,1,0)[x,y,z], h(0,0,1)[x,y,z]}
})
27
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Unit 1.4
2D and 3D Graphing
The graph of a function offers tremendous insight into the behavior of the function and can be of great value in the
solution of problems in mathematics. One of the outstanding features of Mathematica is its graphing capabilities.
Mathematica contains functions for 2D and 3D graphing of functions, lists, and arrays of data.
Basic Plotting
When the Wolfram Language plots a graph for you, it has to make many choices. It has to work out what the scales
should be, where the function should be sampled, how the axes should be drawn, and so on. Most of the time, the
Wolfram Language will probably make pretty good choices. However, if you want to get the very best possible
pictures for your particular purposes, you may have to help the Wolfram Language in making some of its choices.
There is a general mechanism for specifying "options" in Wolfram Language functions. Each option has a definite
name. As the last argument to a function like Plot, you can include a sequence of rules of the form name->value, to
specify the values for various options. Any option for which you do not give an explicit rule is taken to have its
"default" value.
AspectRatio the height‐to‐width ratio for the plot; Automatic sets it from the absolute x and y coordinates
Axes whether to include axes
AxesLabel labels to be put on the axes; ylabel specifies a label for the y axis, {xlabel,ylabel} for both axes
AxesOrigin the point at which axes cross
BaseStyle the default style to use for the plot
FormatType the default format type to use for text in the plot
Frame whether to draw a frame around the plot
FrameLabel labels to be put around the frame; give a list in clockwise order starting with the lower x axis
FrameTicks what tick marks to draw if there is a frame; None gives no tick marks
GridLines what grid lines to include; Automatic includes a grid line for every major tick mark
PlotLabel an expression to be printed as a label for the plot
PlotRange the range of coordinates to include in the plot; All includes all points
Ticks what tick marks to draw if there are axes; None gives no tick marks
PlotStyle a list of lists of graphics primitives to use for each curve (see "Graphics Directives and Options")
ClippingStyle what to draw when curves are clipped
Filling filling to insert under each curve
FillingStyle style to use for filling
PlotPoints the initial number of points at which to sample the function
MaxRecursion the maximum number of recursive subdivisions allowed
28
CHAPTER 1 INTRODUCTION TO MATHEMATICA
]
Output
Input Plot[
{Sin[x],Sin[2 x],Sin[3 x]},
{x,0,2 Pi},
ImageSize->200
]
Output
3D Plot
29
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input ListPlot[
Table[
{Sin[n],Sin[2 n]},
{n,50}
],
ImageSize->200
30
CHAPTER 1 INTRODUCTION TO MATHEMATICA
]
Output
Input ListLinePlot[
{1,1,2,3,5,8},
ImageSize->200
]
Output
Input ListPlot3D[
{{1,1,1,1},{1,2,1,2},{1,1,3,1},{1,2,1,4}},
Mesh->All,
ImageSize->200
]
Output
Input data=Table[
Sin[j^2+i],
{i,0,Pi,Pi/5},
{j,0,Pi,Pi/5}
];
ListPlot3D[
data,
Mesh->None,
InterpolationOrder->3,
ColorFunction->"SouthwestColors",
ImageSize->200
]
31
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Output
Input ListPointPlot3D[
Table[
Sin[j^2+i],
{i,0,3,0.1},
{j,0,3,0.1}
],
ImageSize->200
]
Output
Input ListPointPlot3D[
{
Table[
Sin[j^2+i],
{i,0,3,0.1},
{j,0,3,0.1}
],
Table[
Sin[j^2+i]+3,
{i,0,3,0.1},
{j,0,3,0.1}
]
},
ImageSize->200
]
Output
32
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input DensityPlot[
Sin[x] Sin[y],
{x,-4,4},
{y,-3,3},
ColorFunction->"SunsetColors",
PlotLegends->Automatic,
ImageSize->200
]
Output
Input ContourPlot[
Cos[x]+Cos[y],
{x,0,4 Pi},
{y,0,4 Pi},
PlotLegends->Automatic,
ImageSize->200
]
Output
Combining Plots
33
CHAPTER 1 INTRODUCTION TO MATHEMATICA
]
Output
Input VectorDensityPlot[
{x,-y},
{x,-3,3},
{y,-3,3},
ImageSize->200
]
Output
34
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input VectorPlot3D[
{x,y,z},
{x,-1,1},
{y,-1,1},
{z,-1,1},
ImageSize->200
]
Output
Manipulate
The single command Manipulate lets you create an astonishing range of interactive applications with just a few lines
of input. The output you get from evaluating a Manipulate command is an interactive object containing one or more
controls (sliders, etc.) that you can use to vary the value of one or more parameters. The output is very much like a
small applet or widget: it is not just a static result, it is a running program you can interact with.
35
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input Manipulate[
Plot[
Sin[a x+b],
{x,0,6},
ImageSize->200
],
{a,1,4},
{b,0,10}
]
Output
Input Manipulate[
ContourPlot3D[
x^2+y^2+a z^3==1,
{x,-2,2},
{y,-2,2},
{z,-2,2},
Mesh->None,
ImageSize->200
],
{a,-2,2}
]
Output
36
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input Manipulate[
Plot[
If[t,Sin[x],Cos[x]],
{x,0,10},
ImageSize->200
],
{t,{True,False}}
]
Output
Input Manipulate[
Plot[
f[x],
{x,0,2 Pi},
ImageSize->200
],
{f,{Sin->"sine",Cos->"cosine",Tan->"tangent"}}
]
Output
Input Manipulate[
ParametricPlot[
{a1 Sin[n1 (x+p1)],a2 Cos[n2 (x+p2)]},
{x,0,20 Pi},
PlotRange->1,
PerformanceGoal->"Quality",
ImageSize->200
],
Style["Vertical",Bold,Medium],
{{n1,1,"Frequency"},1,4},
{{a1,1,"Amplitude"},0,1},
{{p1,0,"Phase"},0,2 Pi},
Delimiter,
Style["Horizontal",Bold,Medium],
37
CHAPTER 1 INTRODUCTION TO MATHEMATICA
{{n2,5/4,"Frequency"},1,4},
{{a2,1,"Amplitude"},0,1},
{{p2,0,"Phase"},0,2 Pi},
ControlPlacement->Left
]
Output
Input Manipulate[
Plot3D[
Sin[x y+a],
{x,0,3},
{y,0,3},
ImageSize->200
],
{a,0,1}
]
Output
38
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Unit 1.5
Control Structure
Most programming languages use control structures to control the flow of a program. The control structures include
decision-making and loops. Decision-making is done by applying different conditions in the program. If the conditions
are true, the statements following the condition are executed. The values in a condition are compared by using the
comparison operators. The loops are used to run a set of statements several times until a condition is met. If the
condition is true, the loop is executed. If the condition becomes false, the loop is terminated, and the control passes to
the next statement that follows the loop block.
Conditional Statements
Programmers often need to check the status of a computed intermediate result to branch the program to such or another
block of instructions to pursue the computation. Several examples of the branching condition structures are next.
1- If[condition, t, f] is left unevaluated if the condition evaluates to neither True nor False.
2- If[condition, t] gives Null if the condition evaluates to False.
Input If[
7>8,x,y
39
CHAPTER 1 INTRODUCTION TO MATHEMATICA
]
Output y
Input x=2;
If[
x==0,Print["x is 0"],Print["x is different from 0"]
]
Output x is different from 0
Input x=3;
y=0;
If[
x>1,y=Sqrt[x],y=x^2
];
Print[y]
m:=If[
x>5,1,0
];
Print[m]
Output Sqrt[3]
Output 0
Input a=2;
Which[
a==1,x,
a==2,b
]
Output b
Input expr=3;
Switch[
expr,
1,Print["expr is 1"],
2,Print["expr is 2"],
3,Print["expr is 3"],
_,Print["expr has some other value"
]
]
40
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Output expr is 3
Input k=2;
n=0;
Switch[
k,
1,n=k+10,
2,n=k^2+3,
_,n=-1
];
Print[n]
k=5;
n:=Switch[
k,
1,k+10,
2,k^2+3,
_,-1
];
Print[n]
Output 7
Output -1
Input Piecewise[
{
{x^2,x<0},
{x,x>0}
}
]
41
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input Piecewise[
{
{Sin[x]/x,x<0},
{1,x==0}
},
-x^2/100+1
]
Output Sin[x]/x x<0
1 x == 0
{ x^2
1− True
100
Input Piecewise[
{
{e1,d1},
{e2,d2},
{e3,d2&&d3},
{e4,d4}
},
e
]
Output e1 d1
e2 d2
{
e4 d4
e True
Input x=4;
If[
x>0,
y=Sqrt[x],
y=0
]
Output 2
42
CHAPTER 1 INTRODUCTION TO MATHEMATICA
]
PiecewiseExpand[pw]
Output x x <= 1 2
1 x >= 0 1
{{2 True
({ x True ) ≥ 2
2
3 True
Output 1
1 x >= √2|| <= x <= 1
√2
1 1
2 x >= √2|| <= x <= 1||x <= −
√2 √2
{3 True
Input (* Min, Max, UnitStep, and Clip are piecewise functions of real arguments: *)
PiecewiseExpand/@{
Min[x,y],
Max[x,y,z],
UnitStep[x],
Clip[x,{a,b}]
}
Output x x − y >= 0&&x − z >= 0 a a−x> 0
x x − y <= 0 1 x >= 0
{{ , {y x − y < 0&&y − z >= 0 , { , {b b − x < 0&&a − x <= 0}
y True 0 True
z True x True
Input (* Abs, Sign, and Arg are piecewise functions when their arguments are assumed to
be real: *)
Assuming[
Element[x,Reals],
PiecewiseExpand/@{Abs[x],Sign[x],Arg[x]}
]
Output −1 x < 0
−x x < 0 π x<0
{{ , { 1 x > 0, { }
x True 0 True
0 True
Input x=-4;
y=Which[
x>0,1/x,
x<-3,x^2,
True,0
]
Output 16
43
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input a=-4;
b=4;
y=Switch[
a^2,
a b,1.0/a,
b^2,1.0/b,
_,01
]
Output 0.25
Looping Statements
Mathematica has several looping functions, the most common of which is Do[ ].
Input t=x;
Do[
Print[t=1/(1+k t)],
{k,2,6,2}
]
Output 1/(1+2 x)
1/(1+4/(1+2 x))
1/(1+6/(1+4/(1+2 x)))
Input Do[
Print[{i,j}],
{i,4},
{j,i}
]
Output {1,1}
{2,1}
{2,2}
{3,1}
{3,2}
{3,3}
{4,1}
{4,2}
{4,3}
{4,4}
44
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input sum=0;
Do[
Print[sum=sum+i],
{i,1,4}
];
sum
Output 1
3
6
10
10
Input fact=1;
Do[
Print[fact=fact*i],
{i,1,4}
];
fact
Output 1
2
6
24
24
Input Do[
Do[
Do[
Print["i= ",i," j= ",j," k= ",k],
{i,1,2}
],
{j,1,2}
],
{k,1,2}
]
Output i= 1 j= 1 k= 1
i= 2 j= 1 k= 1
i= 1 j= 2 k= 1
i= 2 j= 2 k= 1
i= 1 j= 1 k= 2
i= 2 j= 1 k= 2
i= 1 j= 2 k= 2
i= 2 j= 2 k= 2
Input sum=0;
Do[
Print[i,",",sum=sum+i^2],
{i,1,6,2}
];
sum
Output 1 , 1
3 , 10
5 , 35
Output 35
Input Do[
Do[
If[Sqrt[i^2+j^2]\[Element]Integers,Print[i," ",j]],
{j,i,10}
],
{i,1,10}
45
CHAPTER 1 INTRODUCTION TO MATHEMATICA
]
Output 3 4
6 8
Input Do[
Print[k!],
{k,3}
]
Output 1
2
6
Input Do[
Print[k," ",k^2," ",k^3],
{k,3}
]
Output 1 1 1
2 4 8
3 9 27
Input Do[
Print[k," squared is ",k^2],
{k,5}
]
Output 1 squared is 1
2 squared is 4
3 squared is 9
4 squared is 16
5 squared is 25
Input Do[
Print[k],
{k,1.6,5.7,1.2}
]
Output 1.6
2.8
4.
5.2
Input Do[
Print[k],
{k,3(a+b),8(a+b),2(a+b)}
]
Output 3 (a+b)
5 (a+b)
7 (a+b)
46
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Output x
x+y
x+2 y
x+3 y
Input Nest[
47
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Function[t,1/(1+t)],x,3
]
Output 1/(1+1/(1+1/(1+x)))
Input NestList[
f,x,4
]
Output {x,f[x],f[f[x]],f[f[f[x]]],f[f[f[f[x]]]]}
Input NestList[
Cos,1.0,10
]
Output {1.,0.540302,0.857553,0.65429,0.79348,0.701369,0.76396,0.722102,0.750418,0.731404,0
.744237}
Input FixedPoint[
Function[t,Print[t];Floor[t/2]],67
]
Output 67
33
16
8
4
2
1
0
Output 0
Input n=17;
While[
n=Floor[n/2];n!=0,
Print[n]
]
Output 8
4
2
1
Input n=1;
While[
n<4,Print[n];
n=n+1
]
Output 1
2
3
Input Do[
Print[i];
If[i>2,Break[]],
{i,10}
]
Output 1
2
3
Input For[
i=1;t=x,
i^2<10,
i=i+1,
48
CHAPTER 1 INTRODUCTION TO MATHEMATICA
t=t^2+i;
Print[t]
]
Output 1+x^2
2+(1+x^2)^2
3+(2+(1+x^2)^2)^2
Input For[
sum=0.0;x=1.0,
(1/x)>0.15,
x=x+1,
sum=sum+1/x;
Print[sum]
]
Output 1.
1.5
1.83333
2.08333
2.28333
2.45
49
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Unit 1.6
Modules, Blocks, and Local Variables
Global Variables are those variables declared in Main Program and can be used by Subprograms. Local Variables are
those variables declared in Subprograms. The Wolfram Language normally assumes that all your variables are global.
This means that every time you use a name like x, the Wolfram Language normally assumes that you are referring to
the same object. Particularly when you write subprograms, however, you may not want all your variables to be global.
You may, for example, want to use the name x to refer to two quite different variables in two different subprograms.
In this case, you need the x in each subprogram to be treated as a local variable. You can set up local variables in the
Wolfram Language using modules. Within each module, you can give a list of variables that are to be treated as local
to the module.
Input Module[
{k},
Do[
Print[k," ",2^k],
{k,3}
]
]
Output 1 2
2 4
3 8
Input k
Output 25
Thus, we can create programs as a series of modules, each performing a specific task. For subtasks, we can embed
modules within other modules to form a hierarchy of operations. The most common method for setting up modules is
through function definitions,
50
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input k
Output 25
Input t=17
Output 17
Input Module[
{t},
t=8;Print[t]
]
Output 8
Input t
Output 17
Input g[u_]:=Module[
{t=u},
t+=t/(1+u)
]
Input g[a]
Output a + a/(1+a)
Input h[x_]:=Module[
{t},
t^2-1/;(t=x-4)>1
]
Input h[10]
Output 35
The format of Module is Module[{var1, var2, ...}, body], where var1, var2, ... are the variables we localize,
and body is the body of the function. The value returned by Module is the value returned by the last operator in the
body (unless an explicit Return[] statement is used within the body of Module. In this case, the argument of
Return[arg] is returned). In particular, if one places the semicolon after this last operator, nothing ( Null) is returned.
As a variant, it is acceptable to initialize the local variables in the place of the declaration, with some global values:
Module[{var1 = value1, var2, ...}, body]. However, one local variable (say, the one "just initialized" cannot
be used in the initialization of another local variable inside the declaration list. The following would be a mistake:
Module[{var1 = value1, var2 = var1, ...}, body]. Moreover, this will not result in an error, but just the global
value for the symbol var1 would be used in this example for the var2 initialization (this is even more dangerous since
no error message is generated and thus we don't see the problem.) In this case, it would be better to do initialization
in steps: Module[{var1=value1,var2,...}, var2=var1;body], that is, include the initialization of part of the
variables in the body of Module. One can use Return[value] statement to return a value from anywhere within the
Module. In this case, the rest of the code (if any) inside Module is slipped, and the result value is returned.
To show how this is done, the following code is an example of a module which will simulate a single gambler
playing the game until the goal is achieved or the money is gone.
51
CHAPTER 1 INTRODUCTION TO MATHEMATICA
var1=var1-1
]
];
Return[
var1==var2
]
]
There are several things to notice in this example. First, this is the same thing we have done in the past to define a
function. That is, we have a function name GamblersRuin with three input variables, a, c, and p. The operator := is
used to start the definition. Secondly, the function involves the Mathematica command Module. This just tells
Mathematica to perform all the commands in the module (like a subroutine in Fortran or a method in C++). There are
some special features we need to understand in the Module command. The Module command has two arguments. The
first argument is a list of all the local variables that will only be used inside the module. In the above example, the
local variable list is {ranval,var1,var2,var3}. These variables are only used in the module and are cleared once
the module has been executed. The second argument is all the commands that will be executed each time the module
is called. There are some assignment commands at the beginning that are used to make things cleaner. The module
uses temporary variables so that the values of the input variables are not overwritten when the module executes.
The last command is added to our list of input lines to return a result from the work done by the Module. Without
this we would never get any results from out calculation. Any recognized variable type or structure within
Mathematica can be returned by a Module. In this example, the returned value is the result of testing two variables in
the code for equality. The code fragment var1==var2 tests to determine if the variables, var1 and var2, are equal. If
the two variables are equal, then the line outputs True and if they are not equal, the line outputs False.
Again, all but the last command must be ended by a semicolon. This is to make sure that the commands are
separated in the execution. Commands separated by blank spaces will be considered as terms to be multiplied together.
Leaving out the semicolon will give rise to lots of error messages, wrong results or both.
Modules in Mathematica allow one to treat the names as local. When one uses Block then the names are global,
but the values are local.
Block[] is automatically used to localize values of iterators in iteration constructs such as Do, Sum, and Table.
Block[] may be used to pack several expressions into one unity.
Input Block[{x=a+1},%]
Output 3+(1+a)^2
Input x
Output x
Input t=17
Output 17
Input Module[
{t},
Print[t]
]
52
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Output t$6220
Input t
Output 17
Input Block[
{t},
Print[t]
]
Output t
53
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Unit 1.7
Functional Programming
In the Wolfram Language, functional programming stands as a highly evolved and seamlessly integrated core feature.
This integration is significantly enhanced by the language's symbolic nature, which imparts richness and convenience.
The approach of treating expressions such as f[x] as both symbolic data and the application of a function f establishes
a uniquely potent method to harmonize structure and function. This synthesis yields an efficient, elegant representation
of numerous common computations.
In the realm of functional programming, several key techniques contribute to the expressive power of the Wolfram
Language:
1. Pure functions: The Wolfram Language embraces the concept of pure functions, enabling the creation of anonymous
functions without the need for formal function definitions. This concise and powerful feature enhances the flexibility
of functional programming.
2. Applying functions repeatedly: Operations like `Nest` facilitate the iterative application of functions, allowing for
the creation of sequences or the exploration of dynamic processes through successive function applications.
3. Applying functions to lists and other expressions: Functions such as `Map` (`/@`), `Apply` (`@@`), and `MapThread`
facilitate the application of functions to lists and expressions, offering versatile tools for element-wise operations,
function application, and coordination across multiple expressions.
4. Building lists from functions: The `Array` function, among others, provides a convenient means to generate lists
based on specified functions. This capability is crucial for efficient data generation and manipulation in a functional
programming paradigm.
Pure Functions
Pure functions are a fundamental concept in functional programming and are used extensively in the Wolfram
Language. When engaging in functional operations like Nest and Map, it is essential to explicitly specify a function
for application. Throughout the examples, we consistently utilized the 'name' of a function to define and apply the
operation. Pure functions provide a more flexible approach, enabling the definition and application of functions
directly to arguments without the need for explicit function names. There are several equivalent ways to write pure
functions in the Wolfram Language.
body& or Function[body] is a pure (or "anonymous") function. The formal parameters are # (or #1),
#2, etc.
54
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input (* This is an equivalent way of expressing the previous pure function, using the `#`
shorthand for the parameter. It also results in `5 + y`: *)
Function[5 + #][y]
Output 5+y
Input (* Another way to write the same expression, using the slot Operator (`#`) directly:
*)
(5 + #) &[y]
Output 5+y
Input (* A pure function taking two parameters `u` and `v` and returning u^4+ v^3: *)
Function[{u, v}, u^4 + v^3][x, y]
Output x^4+y^3
Input (* An alternative way to express the two-parameter pure function using slots: *)
(#1^4 + #2^3) &[x, y]
Output x^4+y^3
Input (* This code assigns the pure function `5 + #` to the symbol `f`: *)
f = (5 + #) &
Output 5+#1&
Input (* Uses `Select` to choose elements greater than 0 from the list: *)
Select[{1, -1, 2, -2, 3}, # > 0 &]
Output {1,2,3}
Input (* Sorts a list of pairs based on the second part of each element: *)
Sort[{{a, 3}, {c, 1}, {d, 2}}, #1[[2]] < #2[[2]] &]
Output {{c,1},{d,2},{a,3}}
Association
In the Wolfram Language, associations stand as key-value pairs, playing a pivotal role alongside lists. These structures
efficiently link keys to corresponding values, enabling rapid lookup and seamless updates, even when dealing with
extensive datasets containing millions of elements. An Association acts like a symbolically indexed list. The value
associated with a given key can be extracted by using the part specification Key[key]. If key is a string, Key can be
omitted.
55
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input (* Uses `Position` to find the position of the value `2` in the association: *)
Position[<|a->4,b->2,c->1,d->5|>,2]
Output {{Key[b]}}
Input (* Extracts the value associated with key `b` as if it were a part: *)
<|a->x,b->y,c->z|>[[Key[b]]]
Output y
Input (* Demonstrates how lookups in associations interoperate with parts in lists and
other expressions: *)
{<|a->x,b->{y,z}|>}[[1,Key[b],2]]
Output z
Input (* Uses `Keys` to extract the list of keys from the association: *)
Keys[<|a->x,b->y,c->z|>]
Output {a,b,c}
Input (* This code uses named arguments from an association, extracting `u` and `v`: *)
g[#u, #v, #u] &[<|"u" -> x, "v" -> y|>]
Output g[x,y,x]
When working with a list of elements in the Wolfram Language, it becomes crucial to apply operations independently
to each element. The Map function comes into play as a versatile mechanism for achieving this. With Map, you can
effortlessly apply a specified function to every individual element within a list. This functionality enhances the
expressiveness and efficiency of your code, allowing for seamless transformations across diverse datasets. Whether
you're manipulating numerical data, symbolic expressions, or custom-defined functions, Map provides a concise and
powerful approach to element-wise operations in the Wolfram Language.
56
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input (* Another way to express the same operation using the short input form: *)
f /@ {a, b, c, d, e}
Output {f[a],f[b],f[c],f[d],f[e]}
Input (* Demonstrates using explicit pure functions with `Map`. The code applies the
function `1 + g[#]` to each element of a list: *)
(1 + g[#]) & /@ {a, b, c, d, e}
Output {1+g[a],1+g[b],1+g[c],1+g[d],1+g[e]}
Input (* Applies the function `f` at the top level of the nested list: *)
Map[f, {{a, b}, {c, d, e}}]
Output {f[{a,b}],f[{c,d,e}]}
Input (* Uses a map operator to apply the function `f` to each element of the list: *)
Map[f][{a, b, c, d}]
Output {f[a],f[b],f[c],f[d]}
In the Wolfram Language, the Map function is a powerful tool for applying a function to each element of a list.
However, there are situations where you may need to apply a function of several arguments to corresponding parts of
different expressions. This is where the MapThread function comes into play. While Map operates on a single list,
MapThread allows you to simultaneously traverse multiple lists, applying a specified function that takes arguments
from corresponding positions in each list. This functionality is particularly useful for handling data in a pairwise or
element-wise manner across several expressions.
57
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input (* Applies the function `f` to corresponding elements of a matrix (nested lists),
considering elements at level 2: *)
MapThread[f,{{{a,b},{c,d}},{{u,v},{s,t}}},2]
Output {{f[a,u],f[b,v]},{f[c,s],f[d,t]}}
Input (* Uses the operator form of `MapThread` to apply the function `f` to corresponding
elements of the given lists: *)
MapThread[f][{{a,b,c,d},{1,2,3,4}}]
Output {f[a,1],f[b,2],f[c,3],f[d,4]}
When dealing with an expression like f[{a, b, c}], you're providing a list as the argument to a function. However,
there are situations where you may want to apply a function directly to the elements of the list, treating each element
as a separate argument. This is where the Apply function, denoted by @@, comes into play. Instead of applying the
function to the list as a whole, Apply allows you to transform the list into individual arguments. The Apply function
is used to change the head of an expression or to "apply" a function to a list of arguments.
Input (* Provides an equivalent way to achieve the same result using the `@@` operator: *)
f@@{a,b,c,d}
Output f[a,b,c,d]
Input (* Sums the elements of the list `{1,2,3,4}` by replacing the head with `Plus`: *)
Plus@@{1,2,3,4}
Output 10
Input (* Applies `f` to the list `{{a,b},{c},d}`, getting rid of one level of lists: *)
f@@{{a,b},{c},d}
Output f[{a,b},{c},d]
Input (* The operator form of `Apply` to achieve the same result as in the previous example:
*)
Apply[f][{{a,b},{c},d}]
Output f[{a,b},{c},d]
Input (* Applies the function `f` to an association, keeping only the values: *)
Apply[f,<|1->a,2->b,3->c|>]
Output f[a,b,c]
58
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Values[<|1->a,2->b,3->c,4->{d}|>]
Output {a,b,c,{d}}
{a,b,c,{d}}
Input (* An equivalent operation using the `@@@` operator, applying `f` to each element of
the list: *)
f @@@ {{a, b}, {c, d}}
Output {f[a,b],f[c,d]}
Input (* This demonstrates the use of the operator form of the assumed `MapApply` function,
applying `f` to each element of the nested list: *)
MapApply[f][{{a, b}, {c}, {d, e}}]
Output {f[a,b],f[c],f[d,e]}
Many programs you write will involve operations that need to be iterated several times. The Nest function in the
Wolfram Language is a powerful tool for iterative computation. Operations like Nest take a function f that operates
on a single argument and apply it successively. In each iteration, the result of the previous step becomes the new
argument for f. This recursive application continues for the specified number of iterations, allowing for the creation
of sequences.
Input (* The function to nest can be a pure function. In this case, it squares and adds 1
to the initial value `1` three times: *)
Nest[(1+#)^2&,1,3]
59
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Output 676
Input (* This example shows how nesting a function can build a formula. The function
`(1+#)^2&` is nested five times, starting with the variable `x`: *)
Nest[(1+#)^2&,x,5]
Output (1+(1+(1+(1+(1+x)^2)^2)^2)^2)^2
Input (* Nesting can return a single number. In this case, the square root of `100.0` is
taken four times: *)
Nest[Sqrt,100.0,4]
Output 1.33352
In the Wolfram Language, operations like Nest are designed to iteratively apply a function f of one argument, using
the result of the previous step as the new argument for each subsequent iteration. This concept becomes even more
powerful when generalized to functions of two arguments. In such cases, the iterative application continues, but each
result obtained provides only one of the new arguments required. A practical approach is to obtain the other argument
at each step from the successive elements of a list, creating a flexible and dynamic process for manipulating data and
performing computations efficiently.
Input (* This code successively applies the function `f` to the seed value `x` and the
elements of the list `{a, b, c, d}`: *)
Fold[f, x, {a, b, c, d}]
Output f[f[f[f[x,a],b],c],d]
Input (* Using `Fold` with the `List` function to create nested ordered pairs: *)
Fold[List, x, {a, b, c, d}]
Output {{{{x,a},b},c},d}
Input (* This code multiplies the elements of the list `{a, b, c, d}` one element at a
time, starting with the seed value `1`: *)
Fold[Times, 1, {a, b, c, d}]
Output a b c d
Input (* Starting the fold operation from the first element of the list: *)
Fold[f, {a, b, c, d}]
Output f[f[f[a,b],c],d]
60
CHAPTER 1 INTRODUCTION TO MATHEMATICA
Input (* Generating an array using a different function. In this case, the function is
`1+#^2&`:*)
Array[1+#^2&,10]
Output {2,5,10,17,26,37,50,65,82,101}
Input (* Generates a 3x2 array where each element is obtained by applying the function `f`
to its indices: *)
Array[f,{3,2}]
Output {{f[1,1],f[1,2]},{f[2,1],f[2,2]},{f[3,1],f[3,2]}}
Input (* Generates an array of length 10 using the pure function `3 + #^3 &`: *)
Array[3 + #^3 &, 10]
Output {2,5,10,17,26,37,50,65,82,101}
61
CHAPTER 1 INTRODUCTION TO MATHEMATICA
62
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
CHAPTER 2
DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Remark:
This chapter provides a Mathematica implementation of the concepts and ideas presented in Chapter 1 of the book
[1] titled Artificial Neural Network and Deep Learning: Fundamentals and Theory. We strongly recommend that
you begin with the theoretical chapter to build a solid foundation before exploring the corresponding practical
implementation. This chapter also serves as a summary of the book titled Statistics for Machine Learning with
Mathematica Applications. For detailed proofs of theorems, additional examples, and comprehensive explanations,
including Mathematica applications, please refer to Ref [2]."
Descriptive statistics form the foundational toolset for summarizing and interpreting data, offering insights into
central tendencies and variability within datasets [3-10]. It serves as the initial lens through which raw data is
scrutinized, paving the way for more advanced analyses. On the other hand, probability theory plays a crucial role in
quantifying uncertainty and randomness inherent in data. It underpins the probabilistic nature of real-world
phenomena, intertwining with statistical measures to create a comprehensive framework for data analysis.
In artificial intelligence (AI) applications, probability theory serves two fundamental purposes:
1. Guiding the rationale behind AI reasoning processes, shaping algorithmic design to compute or approximate
expressions derived from probability.
2. Providing an analytical framework to dissect and evaluate AI system behavior, assessing performance under
diverse conditions and the implications of algorithmic choices.
By integrating probability and statistics in AI development, researchers gain insights into theoretical foundations,
contributing to the refinement and optimization of intelligent systems.
Mathematica provides powerful tools for analyzing and visualizing data, including built-in functions for random
sampling, order and count statistics, frequency distributions, and distribution shapes. By using these functions, you
can gain insights into your data, identify patterns and outliers, and make informed decisions based on statistical
analysis. Additionally, Mathematica offers various functions to compute central tendency, dispersion and shape
measures. These functions provide quick and accurate calculations for determining the typical or central value of a
dataset and for visualizing location statistics.
• Random sampling is a method of selecting a subset of individuals or data points from a larger population in
a way that each member of the population has an equal chance of being selected. In Mathematica, you can
use built-in functions such as RandomSample and RandomChoice to generate random samples from a dataset
or population. These functions can be useful for testing hypotheses, simulating experiments, and exploring
datasets.
• Also, you can use the built-in function Histogram to generate a histogram of the frequency distribution of a
dataset.
• Moreover, you can use the built-in functions PDF, and CDF, to visualize the shape of a distribution.
• The Mean function in Mathematica calculates the arithmetic mean of a list of numbers. It is a commonly used
measure of central tendency and provides the average value of the dataset.
• The Median function computes the middle value of a sorted dataset. It is useful for finding a representative
value that is not influenced by extreme values or outliers.
63
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
• The Commonest function determines the mode(s) of a dataset, which represents the most frequently occurring
value(s). This can be useful when dealing with categorical or discrete data.
• Mathematica provides functions like Quartiles and Quantile to calculate specific quantiles of a dataset.
These functions allow you to find values that divide the dataset into equal proportions, such as the first
quartile (25th percentile) or the median (50th percentile).
• The TrimmedMean function in Mathematica calculates the mean of a dataset after excluding a specified
percentage of extreme values from both ends. It can be useful in situations where outliers may significantly
affect the overall mean.
• The WinsorizedMean function provides a robust measure of central tendency by reducing the impact of
outliers or extreme values on the calculated mean. It achieves this by replacing extreme values with values
from a specified percentile.
• Both the HarmonicMean and GeometricMean functions provide alternative measures of central tendency that
are suitable for specific types of data. While the HarmonicMean is useful for rates and ratios, the
GeometricMean is applicable for multiplicative relationships and positive values.
• Mathematica offers built-in functions for visualizing location statistics. For example, you can create box
plots using BoxWhiskerChart to display the median, quartiles, and potential outliers in a dataset.
• The InterquartileRange function calculates the range between the upper quartile and the lower quartile
in a dataset. It is useful for identifying the spread or dispersion of the middle 50% of the data.
• The QuartileDeviation function calculates the semi-interquartile range, which is half of the Interquartile
Range. It provides a measure of dispersion around the median and is less affected by extreme values.
• The MeanDeviation function computes the average absolute deviation of each data point from the mean. It
gives an indication of the average distance between individual data points and the mean. MeanDeviation is
less influenced by extreme values and provides a robust measure of dispersion.
• The StandardDeviation function calculates the standard deviation, which is a widely used measure of
dispersion. It quantifies the amount of variation or spread in a dataset by measuring the average distance
between each data point and the mean. A higher standard deviation indicates greater variability.
• The Variance function computes the average squared deviation of each data point from the mean. It provides
a measure of the overall variability in a dataset.
• The TrimmedVariance function calculates the variance after trimming a certain percentage of extreme values
from both ends of the dataset. Trimming reduces the impact of outliers and extreme values on the variance
calculation, providing a more robust measure of dispersion.
• The WinsorizedVariance function is similar to TrimmedVariance, but instead of removing extreme values,
it replaces them with values closer to the mean.
• The Moment function computes the nth moment of a dataset.
• The CentralMoment function calculates the nth central moment of a dataset. It measures the dispersion of
data around the mean.
• FactorialMoment function computes the nth factorial moment of a dataset.
• The Skewness function measures the asymmetry of a dataset's distribution. It indicates whether the dataset is
skewed to the left (negative skewness) or to the right (positive skewness) relative to the mean.
• The QuartileSkewness function is a measure of skewness based on quartiles.
• The Kurtosis function measures the peakedness or flatness of a dataset's distribution. It provides insights
into the tail behavior and presence of outliers.
The chapter will include practical examples and exercises to reinforce the concepts learned. By the end of this chapter,
you will be equipped with the knowledge and skills to perform descriptive statistical analysis using Mathematica,
making it easier to summarize and interpret data effectively.
Moreover, we will delve into the world of discrete random variables, which play a crucial role in modeling various
phenomena with countable outcomes. We explore their Probability Mass Functions (PMFs), Cumulative Density
Functions (CDFs), and Moment Generating Functions (MGFs), while leveraging the power of Mathematica to
perform computations and gain insights.
64
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
• PDF and CDF assist in determining the probability density and cumulative probability of discrete random
variables, respectively.
• Expectation and NExpectation functions calculate the expected value or mean of a discrete random
variable, providing insights into its central tendency.
• MomentGeneratingFunction and CentralMomentGeneratingFunction allow for the calculation of higher-
order moments and central moments, offering a more comprehensive understanding of the distribution of the
random variable.
• Mathematica offers a comprehensive set of built-in functions to handle various probability distributions
effortlessly. In this chapter, we also explore two essential probability distributions: Binomial distribution,
and discrete uniform distribution.
Additionally, we explore the world of continuous random variables, which are essential for modeling phenomena
with uncountable outcomes. We study the continuous probability distributions, exploring their Probability Density
Functions (PDFs), CDFs, and MGFs. We will demonstrate how to define, manipulate, and analyze continuous random
variables and probability distributions using Mathematica's syntax and functionality. We will study two fundamental
probability distributions: Normal distribution, and uniform distribution.
By engaging in hands-on exercises and experimenting with different scenarios, readers will enhance their
understanding of the concepts and develop proficiency in utilizing Mathematica for probability analysis.
65
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Unit 2.1
Descriptive Statistics
Mathematica provides a wide range of functions for generating different types of random data, such as integers, real
numbers, vectors, matrices, and graphs which can be useful for a several applications, such as simulations, modeling,
and data analysis.
1. When generating random data, it is important to specify the range and distribution of the data. For example,
you can use the UniformDistribution function to generate data uniformly distributed between a specified
minimum and maximum value, or the NormalDistribution function to generate data following a normal
distribution with a specified mean and standard deviation.
2. The random data generated by Mathematica's built-in functions is pseudo-random, meaning that the sequence
of numbers generated is deterministic and depends on the seed value. It is important to set a specific seed
value using the SeedRandom function if you want to reproduce the same sequence of random numbers.
3. One of the key advantages of Mathematica's random data generation functions is their integration with other
mathematical and statistical functions in the program. This allows users to easily incorporate generated
random data sets into larger simulations and models, and to analyze the results using a wide range of tools.
66
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
{n}
];
ListPlot[
data,
PlotRange->{{0,21},{0,21}},
PlotStyle->Directive[Purple,PointSize[Medium]],
ImageSize->170
]
Output
67
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
rolls=Table[
RandomChoice[Range[6]]+RandomChoice[Range[6]],
{10000}
];
counts=Table[
Count[rolls,i],
{i,2,12}
];
BarChart[
counts,
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ChartLabels->Range[2,12],
ImageSize->220
]
Output
f[x_]:=Sin[x];
Plot[
f[x],
{x,0,2 Pi},
PlotStyle->{Red,Opacity[0.4]},
Epilog->{
PointSize[0.02],
Purple,
Point[
RandomSample[
Table[{x,f[x]},{x,0,2 Pi,0.1}],
10
]
]
},
ImageSize->220
]
68
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Output
Manipulate[
ListPlot[
Table[
RandomVariate[NormalDistribution[μ,σ]],
{n}
],
Filling->Axis,
PlotStyle->{Directive[Purple,Opacity[0.8]]},
PlotRange->{{0,100},{-10,10}},
ImageSize->300
],
{{n,50},1,100,1},
{{μ,0},-5,5,0.1},
{{σ,1},0.1,5,0.1}
]
Output
69
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Some of the most commonly used Mathematica functions include Histogram, and Histogram3D. By using these
functions, you can gain a deeper understanding of the underlying patterns in your data and make informed decisions
based on your findings.
n use n bins
{dx} use bins of width dx
{xmin,xmax,dx} use bins of width dx from xmin to xmax
{{b1,b2,…}} use bins [b1,b2),[b2,b3),…
Automatic determine bin widths automatically
"name" use a named binning method
{"Log",bspec} apply binning bspec on log-transformed data
fb apply fb to get an explicit bin specification {b1,b2,…}
• Possible named binning methods include:
70
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
sampledata=RandomVariate[
NormalDistribution[0,1],
500
];
Table[
Histogram[
sampledata,
Automatic,
heightmethod,
PlotLabel->heightmethod,
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->170
],
{heightmethod,{"Count","Probability","PDF","CumulativeCount","CDF","SF"}}
]
Output
{ , , ,
, , }
71
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Table[
Histogram3D[
sampledata,
Automatic,
height,
PlotLabel->height,
ColorFunction->Function[{height},Opacity[0.9]],
ChartStyle->RGBColor[0.6,0.30,0.60],
ImageSize->170
],
{height,{"Count","Probability","PDF","CDF","SF","HF"}}
]
Output
{ , , ,
, , }
The Wolfram Language's descriptive statistics functions operate both on explicit data and on symbolic representations
of statistical distributions, making it a valuable tool for data analysis and exploratory data science tasks.
Commonest[list] gives a list of the elements that are the most common in list.
Commonest[list,n] gives a list of the n most common elements in list.
TrimmedMean[list,f] gives the mean of the elements in list after dropping a fraction f of the smallest
and largest elements.
TrimmedMean[dist,…] gives the trimmed mean of a univariate distribution dist.
72
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
WinsorizedMean[list,f] gives the mean of the elements in list after replacing the fraction f of the
smallest and largest elements by the remaining extreme values.
WinsorizedMean[dist,…] gives the winsorized mean of a univariate distribution dist.
Quartiles[list] gives a list of the 1/4, 1/2 and 3/4 quantiles of the elements in list.
Quartiles[dist] gives a list of the 1/4, 1/2 and 3/4 quantiles of the distribution dist.
h={133,136,149,133,123,121,140,139,117,117,136,108,126,104,116,147,140,148,150,122,
135,146,133,144,117,124,135,117,120,121,110,124,103,137,101,119,104,113,139,133};
m=N[Mean[h]]
n=Length[h];
ListPlot[
h,
Filling->Axis,
PlotStyle->Purple,
ImageSize->170
]
ListPlot[
{h,{{0,m},{n,m}}},
Joined->{False,True},
Filling->{1->m,2->Axis},
PlotStyle->Purple,
ImageSize->170,
PlotLegends->{None,"Mean =127"}
]
Output 127.
73
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
h={133,136,149,133,123,121,140,139,117,117,136,108,126,104,116,147,140,148,150,122,
135,146,133,144,117,124,135,117,120,121,110,124,103,137,101,119,104,113,139,133};
Tally[h]
c=N[Commonest[h]]
m=Mean[h]
n=Length[h];
ListPlot[
h,
Filling->Axis,
PlotStyle->Purple,
ImageSize->170
]
ListPlot[
{h,{{0,c[[1]]},{n,c[[1]]}},{{0,c[[2]]},{n,c[[2]]}},{{0,m},{n,m}}},
Joined->{False,True,True,True},
Filling->{1->m,2->{3}},
PlotStyle->{Purple,Purple,Purple,Red},
ImageSize->170,
PlotLegends->{"h","Commonest=133","Commonest=117","Mean =127"}
]
Output {{133,4},{136,2},{149,1},{123,1},{121,2},{140,2},{139,2},{117,4},{108,1},{126,1},{
104,2},{116,1},{147,1},{148,1},{150,1},{122,1},{135,2},{146,1},{144,1},{124,2},{12
0,1},{110,1},{103,1},{137,1},{101,1},{119,1},{113,1}}
{133.,117.}
127
SeedRandom[1234];
74
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
The Mathematica function BoxWhiskerChart is a powerful tool for visualizing and analyzing data distributions. Here
are some features of this function:
• Clear representation of data: BoxWhiskerChart provides a clear and concise representation of the
distribution of a dataset. It displays important statistical measures such as the median, quartiles, and outliers,
making it easy to understand the central tendency and spread of the data.
• Customizable appearance: The function offers a wide range of options to customize the appearance of the
box-and-whisker plot. You can adjust the colors, styles, and sizes of the boxes, whiskers, outliers, and other
elements to suit your preferences or match your presentation or publication style.
• Comparative analysis: BoxWhiskerChart allows for easy comparison of multiple datasets. You can plot
several box-and-whisker diagrams side by side or in a stacked manner, making it straightforward to identify
differences or similarities in distributions.
• Interaction and exploration: The resulting chart is interactive, meaning you can hover over different
elements to obtain more detailed information about specific data points or summary statistics. This
interactivity enhances the exploratory data analysis process and allows for a deeper understanding of the
underlying distribution.
75
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
BoxWhiskerChart draws a box-and-whisker summary of the distribution of values in each datai. See the following
figure
76
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
],
{7}
];
BoxWhiskerChart[
data,
"Notched",
ChartStyle->Purple,
ImageSize->200
]
(* Show outliers: *)
BoxWhiskerChart[
data,
"Outliers",
ChartStyle->Purple,
ImageSize->200
]
Output
Output
Table[
BoxWhiskerChart[
data,
{
{"Whiskers",Directive[Thick,s[[2]],Opacity[0.8]]},
{"Fences",Directive[Thick,s[[2]],Opacity[0.8]]}
},
Joined->s[[1]],
PlotLabel->Style[Row[{"Joined - ",s[[1]]}]],
ChartStyle->"Pastel",
ImageSize->200
],
{s,{{"Min",Red},{"Mean",Green},{"Median",Blue},{"Max",Orange}}}
]
77
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Output
{ , ,
, }
data=RandomVariate[NormalDistribution[],{10,100}];
Table[
DistributionChart[
data,
Joined->"Mean",
ChartElementFunction->s,
ChartStyle->"Pastel",
ImageSize->300
],
{s,{"PointDensity","LineDensity"}}
]
Output
{ , }
78
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Dispersion statistics summarize the scatter or spread of the data. Most of these functions describe deviation from a
particular location. For instance, variance is a measure of deviation from the mean. Mathematica provides a set of
functions and tools for calculating, visualizing, and analyzing dispersion statistics, allowing users to gain deeper
insights into the variability and distribution of their data. Let us go through them in detail.
InterquartileRange[list] gives the difference between the upper and lower quartiles for the elements in list.
InterquartileRange[dist] gives the difference between the upper and lower quartiles for the distribution dist.
QuartileDeviation[list] gives the quartile deviation or semi-interquartile range of the elements in list.
QuartileDeviation[dist] gives the quartile deviation or semi-interquartile range of the distribution dist.
MeanDeviation[list] gives the mean absolute deviation from the mean of the elements in list.
79
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
TrimmedVariance[list,f] gives the variance of the elements in list after dropping a fraction f of the smallest
and largest elements.
TrimmedVariance[dist,…] gives the trimmed variance of a univariate distribution dist.
WinsorizedVariance[list,f] gives the variance of the elements in list after replacing the fraction f of the
smallest and largest elements by the remaining extreme values.
WinsorizedVariance[dist,…] gives the winsorized variance of a univariate distribution dist.
sdx=StandardDeviation[data[[All,1]]];
sdy=StandardDeviation[data[[All,2]]];
mx=Mean[data[[All,1]]];
my=Mean[data[[All,2]]];
Print[
"Mean= {" ,mx,",",my,"}, ",
"QuartileDeviation= {",qdx,",",qdy,"}, ",
"StandardDeviation= {", sdx,",",sdy,"} "
]
ListPlot[
data,
Epilog->{
Red, PointSize[0.02],Point[{qdx,qdy}],
Blue, PointSize[0.02],Point[{sdx,sdy}],
Green, PointSize[0.02],Point[{mx,my}]
},
ImageSize->220
]
Output Mean= { -0.0169259 , -0.00549935 }, QuartileDeviation= { 0.676502 , 0.655909
}, StandardDeviation= { 0.998782 , 1.0005 }
80
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
data=RandomVariate[
NormalDistribution[0,1],
1000
];
StandardDeviation[data]
Histogram[
data,
Automatic,
"PDF",
Epilog->{
Red,
PointSize[0.03],
Point[{{StandardDeviation[data],0},{Mean[data],0},{-
StandardDeviation[data],0}}]
},
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->200
]
Output 0.96111
Output
Input (* This code creates a Manipulate function with slider and a dropdown menu. The n
slider allows the user to adjust the sample size, while the dist dropdown menu allows
81
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
the user to choose the distribution that the sample is drawn from. The code then uses
RandomVariate to generate a sample of size n from the selected distribution,
calculates the variance using Variance, and displays both a ListPlot and a Histogram
of the sample data along with the calculated variance. *)
Manipulate[
Module[
{data,var},
data=RandomVariate[dist,n];
var=Variance[data];
Grid[
{
{
ListPlot[
data,
PlotRange->All,
ImageSize->250,
Filling->Axis,
PlotStyle->Purple
],
Histogram[
data,
"FreedmanDiaconis",
"PDF",
Frame->True,
FrameLabel->{"Data","PDF"},
ImageSize->250,
ColorFunction->Function[Opacity[0.7]],
ChartStyle->Purple
]
},
{Null,Text["Variance: "<>ToString[var]]}
}
]
],
{{n,300,"Sample size"},10,1000,10,Appearance-
>"Labeled"},{{dist,NormalDistribution[0,1],"Distribution"},{NormalDistribution[0,1]
,StudentTDistribution[3],ExponentialDistribution[1],UniformDistribution[{-1,1}]}},
Alignment->Center
]
Output
82
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
A variety of moments are used to summarize a distribution or data. Mean is used to indicate a center location, variance
and standard deviation are used to indicate dispersion, etc. The Wolfram Language fully supports moments of any
order, univariate or multivariate, for symbolic distributions and data. Moreover, you can get some information about
the shape of a distribution using shape statistics functions. Skewness describes the amount of asymmetry. Kurtosis
measures the concentration of data around the peak and in the tails versus the concentration in the flanks. let us start
by considering moment functions.
CentralMoment[list,r] gives the r^(th) central moment of the elements in list with respect to their mean.
CentralMoment[dist,r] gives the r^(th) central moment of the distribution dist.
QuartileSkewness[list] gives the coefficient of quartile skewness for the elements in list.
QuartileSkewness[dist] gives the coefficient of quartile skewness for the distribution dist.
Manipulate[
Module[
{data,mean,centralMoment},
(*Generate sample data from a distribution*)
data=RandomVariate[Distribution,sampleSize];
(*Calculate central moment*)
centralMoment=CentralMoment[data,n];
(*Plotting the histogram*)
83
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Histogram[
data,
Automatic,
"PDF",
PlotRange->All,
PlotLabel->{Text["Central Moment ("<>ToString[n]<>"):
"<>ToString[centralMoment]]},
ImageSize->300,
ColorFunction->Function[Opacity[0.5]],
ChartStyle->Purple
]
],
(*Manipulate parameters*)
{{Distribution,NormalDistribution[0,1],"Distribution:"},{NormalDistribution[0,1]-
>"Normal",GammaDistribution[2,1]->"Gamma",UniformDistribution[{-1,1}]-
>"Uniform"}},{{sampleSize,1000,"Sample Size:"},{100,500,1000,5000}},
{{n,2,"Order of Central Moment:"},{1,2,3,4}}
]
Output
dist1=SkewNormalDistribution[0,1,-3]; (* α=-3*)
dist2=SkewNormalDistribution[0,1,0]; (* α=0*)
dist3=SkewNormalDistribution[0,1,3]; (* α=3*)
skewness1=N[Skewness[dist1]];
skewness2=N[Skewness[dist2]];
skewness3=N[Skewness[dist3]];
Plot[
{PDF[dist1,x],PDF[dist2,x],PDF[dist3,x]},
{x,-5,5},
PlotStyle->{Purple,Darker[Red],Darker[Blue]},
Filling->Axis,
PlotLegends->{
84
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
"Skewness = "<>ToString[skewness1],
"Skewness = "<>ToString[skewness2],
"Skewness = "<>ToString[skewness3]
},
Frame->True,
FrameLabel->{"x","PDF"},
PlotRange->All,
ImageSize->250
]
Output
85
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Unit 2.2
Probability Distributions
PDF[dist,x] gives the probability density function for the distribution dist evaluated at x.
CDF[dist,x] gives the cumulative distribution function for the distribution dist evaluated at
x.
MomentGeneratingFunction[dist,t] gives the moment-generating function for the distribution dist as a function of
the variable t.
PDF[NormalDistribution[μ,σ],x]
CDF[NormalDistribution[μ,σ],x]
MomentGeneratingFunction[NormalDistribution[μ,σ],x]
Mean[NormalDistribution[μ,σ]]
Variance[NormalDistribution[μ,σ]]
Output (x−μ)2
− 2
𝑒 2σ
√2𝜋 σ
Output 1 −x + μ
Erfc[ ]
2 √2 σ
Output x2 σ2
𝑒 x μ+ 2
Output μ
Output σ^2
DiscretePlot3D[
pdf,
{x,0,10},
{y,0,10},
ExtentSize->0.6,
PlotStyle->Purple,
ImageSize->200
]
DiscretePlot3D[
pdf,
{x,0,10},
{y,0,10},
PlotRange->All,
PlotStyle->Purple,
ImageSize->200
]
86
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Output
DiscreteUniformDistribution[{imi represents a discrete uniform distribution over the integers from imin to imax.
n,imax}]
DiscreteUniformDistribution[{{im represents a multivariate discrete uniform distribution over integers within the
in,imax},{jmin,jmax},…}] box {{imin,imax},{jmin,jmax},…}.
NormalDistribution[μ,σ] represents a normal (Gaussian) distribution with mean μ and standard deviation
σ.
NormalDistribution[] represents a normal distribution with zero mean and unit standard deviation.
87
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
DiscretePlot[
Evaluate[
Table[
PDF[
BinomialDistribution[30,p],k
],
{p,{0.2,0.5,0.7}}
]
],
{k,37},
PlotRange->All,
PlotMarkers->Automatic,
PlotLegends->Placed[{"n=30,p=0.2","n=30,p=0.5","n=30,p=0.7"},{0.8,0.75}],
PlotStyle->{RGBColor[0.88,0.61,0.14],RGBColor[0.37,0.5,0.7],Purple},
ImageSize->320,
AxesLabel->{None,"PMF"}
]
Output
DiscretePlot[
Evaluate[
Table[
PDF[
DiscreteUniformDistribution[{1,b}],j
],
{b,{8,12,16}}
]
],
{j,26},
ExtentSize->1/2,
PlotRange->All,
PlotMarkers->Automatic,
PlotLegends->Placed[{"a=1,b=8","a=1,b=12","a=1,b=16"},{0.8,0.75}],
88
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
PlotStyle->{RGBColor[0.88,0.61,0.14],RGBColor[0.37,0.5,0.7],Purple},
ImageSize->250,
AxesLabel->{None,"PMF"}
]
Output
Manipulate[
Module[
{
data=RandomVariate[
UniformDistribution[{min,max}],n
]
},
Show[
Histogram[
data,
Automatic,
"PDF",
ColorFunction->Function[{height},Opacity[height]],
ImageSize->320,
ChartStyle->Purple
],
Plot[
PDF[
UniformDistribution[{min,max}],x
],
{x,0,7},
ColorFunction->"Rainbow"
]
]
],
{{min,1,"min"},1,4,0.1},
{{max,4.5,"max"},4.5,7,0.1},
{{n,300,"n"},100,1000,10}
]
89
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Output
data=RandomVariate[
UniformDistribution[{0,6}],
{1000,2}
];
GraphicsRow[
{
Histogram[
data[[All,1]],
{0.1},
PlotLabel->"X-axis",
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple
],
Histogram[
data[[All,2]],
{0.1},
PlotLabel->"Y-axis",
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple
],
ListPlot[
data,
PlotStyle->{Purple,PointSize[0.015]},
AspectRatio->1,
Frame->True,
Axes->False
]
}
]
90
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Output
Plot[
Evaluate[
Table[
PDF[
NormalDistribution[0,σ],
x
],
{σ,{.75,1,2}}
]
],
{x,-7,7},
PlotRange->All,
Filling->Axis,
PlotLegends->Placed[{"μ=0,σ=0.75","μ=0,σ=1","μ=0,σ=2"},{0.8,0.75}],
PlotStyle->{RGBColor[0.88,0.61,0.14],RGBColor[0.37,0.5,0.7],Purple},
ImageSize->320,
AxesLabel->{None,"PDF"}
]
Output
91
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->320,
AxesLabel->{None,"PDF"}
],
Plot[
PDF[
NormalDistribution[1,3],
x
],
{x,-9,9},
PlotStyle->RGBColor[0.88,0.61,0.14],
PlotRange->{0,4}
]
]
Output
data=RandomVariate[
NormalDistribution[0,1],
{1000,3}
];
GraphicsGrid[
{
{
Histogram[
data[[All,1]],
Automatic,
"PDF",
PlotLabel->"X-axis",
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple
],
Histogram[
data[[All,2]],
Automatic,
"PDF",
PlotLabel->"Y-axis",
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple
],
Histogram[
data[[All,3]],
Automatic,
92
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
"PDF",
PlotLabel->"Z-axis",
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple
],
ListPointPlot3D[
data,
BoxRatios->{1,1,1},
PlotStyle->{Purple,PointSize[0.015]}
]
}
}
]
Output
Manipulate[
dist1=NormalDistribution[mean1,sd1];
dist2=NormalDistribution[mean2,sd2];
distSum=TransformedDistribution[
x+y,
{Distributed[x,dist1],Distributed[y,dist2]}
];
Plot[
{
PDF[dist1,x],
PDF[dist2,x],
PDF[distSum,x]
},
{x,-5,5},
PlotRange->All,
AxesLabel->{"x","f(x)"},
Filling->{1->{2},2->{3}},
FillingStyle->{LightBlue,LightPurple},
PlotLegends->{"Distribution 1","Distribution 2","Sum of Distributions"}
],
{{mean1,0,"Mean 1"},-5,5,Appearance->"Labeled"},
{{sd1,1,"Standard Deviation 1"},0.1,5,Appearance->"Labeled"},
{{mean2,0,"Mean 2"},-5,5,Appearance->"Labeled"},
{{sd2,1,"Standard Deviation 2"},0.1,5,Appearance->"Labeled"}
]
93
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Output
94
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
estim0distributions=Table[
dist=NormalDistribution[0,1];
sampledata=RandomVariate[
dist,
100
];
ed=EstimatedDistribution[
sampledata,
NormalDistribution[α,β]
],
{i,1,20}
]
pdf0ed=Table[
PDF[estim0distributions[[i]],x],
{i,1,20}
];
ListPlot[
table,
ImageSize->320,
Filling->Axis,
PlotStyle->Directive[Opacity[0.5],Thickness[0.003]]
]
95
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
Histogram[
table,
Automatic,
LabelingFunction->Above,
ChartLegends->{"Sample 1","Sample 2"},
ChartStyle->{Directive[Opacity[0.2],Red],Directive[Opacity[0.2],Purple]},
ImageSize->320
]
Output
Output
Output
96
CHAPTER 2 DESCRIPTIVE STATISTICS AND PROBABILITY THEORY
97
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
CHAPTER 3
MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Remark:
This chapter provides a Mathematica implementation of the concepts and ideas presented in Chapter 2, [1], of the
book titled Artificial Neural Network and Deep Learning: Fundamentals and Theory. We strongly recommend that
you begin with the theoretical chapter to build a solid foundation before exploring the corresponding practical
implementation. This chapter also serves as a summary of the book titled Mathematics for Machine Learning and
Data Science: Optimization with Mathematica Applications. For detailed proofs of theorems, additional examples,
and comprehensive explanations, including Mathematica applications, please refer to Ref [11]."
In the realm of AI and machine learning, the modern development of NNs stands as a testament to the marriage of
sophisticated mathematical frameworks and computational ingenuity. At the heart of this evolution lies the profound
influence of matrix calculus [12-14] and gradient optimization techniques [15-23]. These foundational pillars have
not only reshaped the landscape of NN design but have also propelled advancements in diverse domains, ranging from
computer vision to natural language processing and beyond.
Matrix calculus, with its roots in linear algebra, provides a powerful toolset for analyzing and manipulating
multidimensional data structures. It offers a systematic framework for computing derivatives and gradients of
functions involving matrices and vectors, enabling efficient optimization in high-dimensional spaces. Matrix calculus
is indeed essential for building and training NNs. NNs, especially deep learning models, heavily rely on matrix
operations for their computations.
• NNs are typically represented and implemented using matrices and vectors. Each layer in a NN can be seen
as a matrix operation, where inputs (vectors) are multiplied by weights (matrices) and passed through
functions (activation functions).
• The training of NNs often involves optimization algorithms like Gradient Descent (GD). Matrix calculus
provides the necessary tools to compute gradients efficiently, enabling the optimization process to update the
network parameters (weights) in the direction that minimizes the objective (loss) function.
• Backpropagation is the primary algorithm used to compute gradients efficiently in NNs. It is essentially an
application of the chain rule from calculus, which involves matrix multiplication and transposition
operations.
• Matrix calculus allows for efficient computation of derivatives and gradients in NNs. This efficiency is
crucial for training deep NNs, which may have millions of parameters.
• Most deep learning frameworks handle much of the matrix calculus under the hood. However, understanding
the underlying principles of matrix calculus can help in debugging, optimizing, and customizing NN
architectures.
Complementing matrix calculus is the arsenal of gradient optimization techniques, which are fundamental to
training NNs. By iteratively adjusting model parameters in the direction of steepest descent, these methods seek to
minimize a predefined objective function, such as the loss function in supervised learning tasks. From classic
algorithms like GD to more advanced variants like Stochastic Gradient Descent (SGD) and Adaptive Moment (Adam)
optimization, these techniques play a pivotal role in navigating the vast landscape of model parameter space efficiently
and effectively.
98
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
This chapter aims to introduce the concepts of numerical differentiation, matrix calculus, gradient optimization,
and demonstrate their implementation using Mathematica.
This chapter will include detailed explanations, examples, and Mathematica code snippets to ensure a comprehensive
understanding of these topics.
(* Print results: *)
Print["Forward Difference Approximation: ",forwardDifference]
Print["Backward Difference Approximation: ",backwardDifference]
Print["Central Difference Approximation: ",centralDifference]
Print["Exact Derivative: ",N[exactDerivative]]
99
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Show[plotFunction]
Manipulate[
Module[
{f,x0,forwardDifference,backwardDifference,centralDifference,exactDerivative,plo
tFunction},
(* Define the function to differentiate: *)
f[x_]:=Sin[x];
(* Define the point at which to approximate the derivative: *)
x0=Pi/4;
100
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
PlotStyle->{Blue,Red,Green,Purple},
PlotLegends->{"f[x]","Forward Approximation","Backward
Approximation","Central Approximation"},
Epilog->{
Red,
PointSize[Large],
Point[{x0,f[x0]}],
Text["x0",{x0,f[x0]},{1,-1}]
},
PlotLabel->"Function and Numerical Approximations",
AxesLabel->{"x","f[x]"},
ImageSize->300
]
}
]
],
(* Manipulate control for step size (h): *)
{{h,0.1,"Step size (h)"},0.001,2,0.01}
]
101
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output
Output {a1,a2,a3}
102
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Tr[Transpose[A].X]
f[X_]:=Tr[Transpose[A].X]
(* Compute the derivative with respect to each element of the matrix X: *)
grad=Table[D[f[X],X[[i,j]]],{i,1,2},{j,1,2}]
103
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output
104
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
105
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Now, let's consider a simple example to illustrate how the gradient descent method works. Mathematica codes 3.12
and 3.13 create interactive visualization demonstrating the gradient descent optimization process for a one- and two-
dimensional loss function, respectively. Here's an overview of how the Mathematica codes 3.12 achieves this goal:
• The code defines a quadratic loss function 𝐽(𝜃) = (𝜃 − 3)2 + 5, representing a curve in a one-dimensional
space.
• The `GradientDescent` function is implemented to perform the gradient descent optimization algorithm. This
function iteratively updates the parameter 𝜃 based on the gradient of the loss function until convergence or
the maximum number of iterations is reached. It returns the history of parameter values during optimization.
• The `Manipulate` function from Mathematica is utilized to create an interactive interface. Users can adjust
parameters such as the learning rate, initial guess for 𝜃, tolerance for convergence, and maximum iterations.
The interface dynamically updates the visualization based on user inputs.
• The loss function curve 𝐽(𝜃) is plotted against the parameter 𝜃. Additionally, the optimization path taken by
gradient descent is displayed as a sequence of points (red) and arrows (blue) on the plot. Users can observe
and analyze how changes in the parameters influence the optimization process and its convergence towards
the minimum of the loss function.
Let's discuss how users can observe the effects on the optimization path and convergence behavior using the provided
interactive visualization.
1. The learning rate determines the step size of each iteration in the gradient descent algorithm. Users can adjust
the learning rate using the slider labeled "Learning Rate." A higher learning rate may lead to faster
convergence but can also cause overshooting or oscillations around the minimum. Conversely, a lower
learning rate may result in slower convergence but with more stable behavior. Users can experiment with
different learning rates to observe how they affect the optimization path and convergence behavior.
2. The initial guess for the parameter 𝜃 determines the starting point of the optimization process. Users can
adjust the initial guess using the slider labeled "Initial Guess." Different initial guesses may lead to different
optimization paths and convergence behaviors. Users can explore how changing the initial guess influences
the optimization path and convergence behavior.
3. The tolerance parameter determines the convergence criterion for the optimization process. If the absolute
gradient of the loss function falls below the tolerance value, the optimization process is considered converged.
Users can adjust the tolerance using the slider labeled "Tolerance." A smaller tolerance value leads to stricter
convergence criteria, potentially requiring more iterations for convergence. Users can observe how changing
the tolerance affects the number of iterations and convergence behavior.
4. The maximum iterations parameter limits the number of iterations allowed for the optimization process. If
the optimization process does not converge within the specified maximum iterations, it terminates. Users can
adjust the maximum iterations using the slider labeled "Max Iterations." Setting a higher maximum iterations
value allows for more iterations, potentially leading to convergence even with slower convergence rates.
Users can experiment with different maximum iterations settings to observe their effects on convergence
behavior.
106
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
can observe and analyze how changes in the parameters influence the optimization
process and its convergence towards the minimum of the loss function: *)
Manipulate[
Module[
{θHistory,θOpt,minLoss},
(* Controls: *)
{{α,0.1,"Learning Rate"},0.01,1,0.01,Appearance->"Labeled"},
{{θ0,0.0,"Initial Guess"},-2,5,0.1,Appearance->"Labeled"},
{{tol,0.0001,"Tolerance"},0.00001,0.001,0.00001,Appearance->"Labeled"},
{{maxIter,1,"Max Iterations"},1,15,1,Appearance->"Labeled"}
]
107
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output
108
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
{x,-2,5},
{y,-2,5},
PlotLabel->"Gradient Descent Optimization",
AxesLabel->{"x","y"},
PlotRange->All,
Epilog->{Blue,PointSize[0.02],Point[history]},
Contours->Function[{min,max},Range[min,max,5]],
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
PlotLegends->Automatic,
LabelStyle->Directive[Black,10],
ImageSize->250
];
(* Add arrows to the contour plot: *)
arrows=Graphics[
{
Red,Arrowheads[0.03],
Arrow/@Partition[history,2,1]
},
PlotRange->All
];
(* Combine the contour plot and arrows: *)
Show[contourPlot,arrows]],
(* Controls: *)
{{x0,0.0,"Initial x"},-2,5,Appearance->"Labeled"},
{{y0,0.0,"Initial y"},-2,5,Appearance->"Labeled"},
{{α,0.1,"Learning Rate"},0.01,1,Appearance->"Labeled"},
{{tol,0.0001,"Tolerance"},0.0001,0.1,Appearance->"Labeled"},
{{maxIter,1,"Max Iterations"},1,100,1,Appearance->"Labeled"},
TrackedSymbols:>{x0,y0,α,tol,maxIter}
]
Output
109
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Moreover, for many real-world optimization problems involving multivariable functions, analytical solutions may not
be feasible, and numerical methods like the conjugate gradient, principal axis, Levenberg Marquardt, Newton, quasi
Newton, interior point, and linear programming, are indispensable for finding approximate solutions. Each method
has its advantages and limitations, and the choice of method depends on the specific characteristics of the optimization
problem at hand. In the following chapters of this book, we will explore numerical optimization methods for neural
networks in depth. For now, let us utilize Mathematica to implement solutions for optimization problems. We focus
on the practical utilization of Mathematica's optimization functions for optimization problems. From identifying
optimal solutions to visualizing the optimization process, Mathematica equips users with powerful tools to tackle a
wide array of optimization challenges efficiently and accurately.
The commands FindMinimum, NMinimize, Minimize and FindMinimumPlot can do optimization for both single-
variable and multivariable functions.
FindMinimum
FindMinimum[f,x]
searches for a local minimum in f, starting from an automatically selected point.
FindMinimum[f,{x,x0}]
searches for a local minimum in f, starting from the point x=x0.
FindMinimum[f,{{x,x0},{y,y0},…}]
searches for a local minimum in a function of several variables.
FindMinimum[{f,cons},{{x,x0},{y,y0},…}]
searches for a local minimum subject to the constraints cons.
FindMinimum[{f,cons},{x,y,…}]
starts from a point within the region defined by the constraints.
The following options can be given:
NMinimize
NMinimize[f,x]
searches for a global minimum in f numerically with respect to x.
NMinimize[f,{x,y,…}]
searches for a global minimum in f numerically with respect to x, y, ….
NMinimize[{f,cons},{x,y,…}]
searches for a global minimum in f numerically subject to the constraints cons.
NMinimize[…,x∈rdom]
constrains x to be in the region or domain rdom.
110
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Minimize[f,{x,y,…}]
minimizes f symbolically with respect to x, y, ….
Minimize[{f,cons},{x,y,…}]
minimizes f symbolically subject to the constraints cons.
Minimize[…,x∈rdom]
constrains x to be in the region or domain rdom.
Minimize[…,…,dom]
constrains variables to the domain dom, typically Reals or Integers.
Remarks:
• Minimize is also known as infimum, symbolic optimization and global optimization (GO).
• Minimize finds the global minimum of f subject to the constraints given.
• N[Minimize[…]] calls NMinimize for optimization problems that cannot be solved symbolically.
111
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output 87/16
Output 2
Output -6
Output {
{\[Piecewise], {
{d, c==0&&a>=0&&b==0},
{(-c^2+4 a d)/(4 a), (c>0&&a>0&&b==0)||(c<0&&a>0&&b==0)},
{-∞, True}
}}
}
Output 5.4375
Output 2.
Output -6.
112
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output 5.4375
Output 2.
Output -6.
Output 0.790545
Output {1.8151,0.839899}
Output {0.,-2.}
113
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output {0.790569}
Output {1.41421,1.41421}
Output {0.,-2.}
(* Find the minimum value of the function over the specified rectangle: *)
minValue=MinValue[
f[x,y],
{x,y}\[Element]Rectangle[{0,0},{1,1}]
];
(* Find the minimizer point of the function over the specified rectangle: *)
minPoint=ArgMin[
f[x,y],
{x,y}\[Element]Rectangle[{0,0},{1,1}]
];
(* Create a 3D point with the coordinates of the minimizer point and the
corresponding function value: *)
minPoint3D={minPoint[[1]],minPoint[[2]],f[minPoint[[1]],minPoint[[2]]]};
(* Plot the function over the specified rectangle and highlight the minimum point:
*)
Show[
(* 3D plot of the function: *)
Plot3D[
f[x,y],
{x,0,1},
{y,0,1},
PlotRange->All,
AxesLabel->{"x","y","f(x, y)"},
PlotLabel->"Plot of f(x, y) = Sin[x] * Cos[y] over \n the rectangle [0, 0] to
[1, 1]",
ColorFunction->"BlueGreenYellow",
Mesh->None,
ImageSize->250
],
Graphics3D[
{
Blue,
PointSize[Large],
(* Highlight the minimum point on the 3D plot:*)
114
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Point[minPoint3D],
Text[Style["Minimum Value",Blue,Bold],minPoint3D,{-1,1}]
}
]
]
Output
115
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
116
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output {-11.6378,{x->3.6436}}
Output 3.6436
Output
(* Plot it: *)
Show[
(* Contour plot of the function over the specified rectangle: *)
ContourPlot[
x^2+y^2,
{x,-1,1},
{y,-1,1},
Contours->10,
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
PlotLegends->Automatic,
ImageSize->250,
PlotLabel->"Contour Plot of x^2 + y^2 over a Rectangle"
],
Graphics[
{
Purple,
PointSize[Large],
(* Plot a point at the minimum found in the previous FindMinimum call: *)
Point[{x,y}/. Last[%]]
}
]
]
Output {2.,{x->1.,y->1}}
Output {0.,{x->0.,y->0.}}
117
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output
Output {-7.33508,{x->1.90438,y->1.8218}}
118
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output
Output {e,{{a,c,d}}}
Output {395,{{1,4,9,16,25,36,49,64,81,100}}}
119
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Plot[
f[x],
{x,.1,1.5},
Epilog->{Red,Map[Point,steps[[1]]]},
LabelStyle->Directive[Black,12],
ImageSize->250
]
Output {{3.44228,{x->0.703467}}, {{{1.5,5.14836}, {1.12002,3.95775}, {0.633045,3.463},
{0.736537,3.44639}, {0.706923,3.44232}, {0.703306,3.44228}, {0.703468,3.44228},
{0.703467,3.44228}}}}
Output
120
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
},
Contours->10,
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
PlotLegends->Automatic,
ImageSize->250,
PlotLabel->"Contour Plot of Rosenbrock Function\n with Minimization Steps"
]
Output
(* Record all the points evaluated during the solution process of a function with
a ring of minima: *)
(* Use NMinimize to find the minimum and track the evaluated points: *)
{solution,evaluatedPoints}=Reap[
NMinimize[
ringMinimaFunction[x,y],
{{x,-5,5},{y,-5,5}},
(*Optimization method*)
Method->"DifferentialEvolution",
(*Track and store the points evaluated by the algorithm*)
EvaluationMonitor:>Sow[{x,y}]
]
];
(* Plot all the visited points that are close in objective function value to the
final solution: *)
ContourPlot[
121
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
ringMinimaFunction[x,y],
{x,-5,5},
{y,-5,5},
Epilog->
{
Red,
Map[
(*Plot points at each evaluated point*)
Point,
Cases[
(*Extract the evaluated points*)
First[evaluatedPoints],
122
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
steps=Reap[
FindMinimum[
targetFunction[x,y],
(* Initial guesses for x and y: *)
{{x,-1.2},{y,1}},
(* Track and store the steps taken by the algorithm: *)
StepMonitor:>Sow[{x,y}]
]
][[2,1]];
(* Create a contour plot of the logarithm of the function with the steps: *)
ContourPlot[
Log[
targetFunction[x,y]],
{x,-1.3,1.5},
{y,-1.5,1.4},
Epilog->{
Red,
(* Draw a line through the steps taken: *)
Line[steps],
(* Plot points at each step: *)
Point[steps]
},
Contours->10,
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
PlotLegends->Automatic,
ImageSize->250,
PlotLabel->"Contour Plot of Logarithm of \n Target Function with Minimization
Steps"
]
Output
123
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Input (* The code achieves the following goals: it defines a target function (1-x)^2+100
(-x^2-y)^2+1 to minimize. It then defines a function `minimizeAndPlot` that performs
minimization using a specified optimization method, tracks the steps taken during
the optimization process, and creates a contour plot of the logarithm of the target
function with the steps highlighted. Finally, it calls the `minimizeAndPlot`
function for each of the specified optimization methods ("Newton", "QuasiNewton",
"ConjugateGradient", "PrincipalAxis", "LevenbergMarquardt", "InteriorPoint"),
generating contour plots that visualize the optimization path for each
method,providing insights into the behavior and efficiency of each optimization
technique: *)
124
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output
FindMinimum::lstol: The line search decreased the step size to within the
tolerance specified by AccuracyGoal and PrecisionGoal but was unable to find a
sufficient decrease in the function. You may need more than MachinePrecision
digits of working precision to meet these tolerances.
Output
Output
125
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output
Output
Output
126
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
127
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output
<<Optimization`UnconstrainedProblems`
128
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
129
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
Output
Output
Output {{-2.,{x->1.37638,y->1.67868}},{-2.,{x->1.37638,y->1.67868}},{-2.,{x->1.37638,y-
>1.67868}},{-0.179902,{x->4.94463*10-9,y->0.905726}}}
Output {{{-2.,{x->1.37638,y->1.67868}},{Steps->5,Function->6,Gradient->6},{
{ , }
}},{{-2.,{x->1.37638,y->1.67868}},{Steps->9,Function->13,Gradient->13},{
130
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
{ , }
}},{{-2.,{x->1.37638,y->1.67868}},{Steps->10,Function->32,Gradient->32},{
{ , }
}},{{-0.179902,{x->4.94463*10-9,y->0.905726}},{Steps->1,Function->56},{
{ , }
}}}
131
CHAPTER 3 MATRIX CALCULUS AND GRADIENT OPTIMIZATION
132
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
CHAPTER 4
MULTILAYER FEED-FORWARD NEURAL NETWORK
Remark:
This chapter provides a Mathematica implementation of the concepts and ideas presented in Chapter 3, [1], of the
book titled Artificial Neural Network and Deep Learning: Fundamentals and Theory. We strongly recommend that
you begin with the theoretical chapter to build a solid foundation before exploring the corresponding practical
implementation.
In the rapidly evolving landscape of AI and machine learning [24-39], Feed-Forward Neural Networks (FFNNs)
stand out as foundational structures, powering a multitude of applications across various domains. This chapter serves
as a comprehensive introduction to the inner workings of FFNNs, delving into essential concepts and mechanisms
crucial for understanding their functionality and effectiveness. We will start by looking at the structure of a FFNN,
followed by how they are trained and used for making predictions. We will also take a brief look at the loss functions
that should be used in different settings, the Activation Functions (AFs) used within a neuron, and the different types
of optimizers that could be used for training.
The training process is a crucial phase in the development of FFNNs, enabling them to learn from data and improve
their performance over time. The training procedure can be broken down into two main components, each playing a
distinct role in the network's learning process (forward propagation and back propagation).
We begin with an exploration of forward propagation in NNs, elucidating how input data traverse through the
network's layers to produce output predictions. Through a step-by-step examination, readers will grasp the
fundamental principles underlying the propagation of information within these intricate systems.
A pivotal aspect of NN training is automatic differentiation and its main modes [40-43]. Automatic differentiation
illustrates the mechanisms through which gradients are computed efficiently, enabling the network to adapt and
optimize its parameters during the learning process. We further explore the training process and loss/cost functions
integral to optimizing NNs. From defining objectives through appropriate loss functions to navigating the landscape
of optimization algorithms.
We shift our focus to the backward pass, often referred to as Back Propagation (BP). During this phase, the network
evaluates the error or the disparity between its predictions (outputs) and the actual target values. This discrepancy
serves as a guide for adjusting the network's weights to minimize the error and enhance its accuracy. BP involves
traversing the network in reverse, updating weights based on the calculated error and its gradients.
Moreover, we explore the Universal Approximation Theorem (UAT) [44-46], which asserts that a FFNN with a
single hidden layer can approximate any continuous function on a compact subset of ℝ𝑛 . This theorem underscores
the remarkable flexibility and potential of NNs in modeling complex, non-linear relationships.
In this chapter, we focus on the practical aspects of constructing NNs using Mathematica. We explore a variety of
essential components and techniques for building NNs, ranging from fundamental layers to complex architectures.
• First, we will delve into the intricacies of constructing NNs from scratch using Mathematica. By exploring
the foundational elements and step-by-step processes, you'll gain a comprehensive understanding of NN
architecture, training methodologies, and performance optimization.
• Next, we begin by understanding the foundational building block of NNs, the LinearLayer. This layer
performs linear transformations on the input data, playing a crucial role in connecting different layers of the
network. The key components of a LinearLayer are the weights and biases. During the training process,
these parameters are adjusted iteratively using optimization algorithms such as gradient descent, enabling the
133
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
network to learn from the data. The number of input features and the number of neurons in the LinearLayer
determine the dimensions of the weight matrix.
• As we progress, we introduce the ElementwiseLayer, which enables element-wise operations such as ReLU
AF or sigmoid activation across the network's neurons. This layer adds non-linearity to the network, allowing
it to learn complex patterns in the data. Mathematica provides options for customizing ElementwiseLayers,
such as choosing different AFs, or defining custom AFs, allowing practitioners to tailor the behavior of
ElementwiseLayers according to the specific requirements of their tasks.
• We explore two essential constructs for organizing NN architectures: NetChain and NetGraph. NetChain
enables the sequential composition of layers, where the output of one layer serves as the input to the next
layer. This sequential arrangement facilitates the construction of straightforward feedforward NN
architectures, where data flows from input to output through a series of transformations. Creating a NetChain
in Mathematica involves specifying the layers and their configurations sequentially.
• NetGraph is a powerful construct in Mathematica for building NN architectures that involve non-sequential
or more complex connectivity patterns. Unlike NetChain, which represents a linear sequence of layers,
NetGraph allows for the creation of arbitrary computational graphs, enabling the design of intricate NN
structures. NetGraph enables the creation of NNs with arbitrary connectivity patterns, where layers can be
connected in any configuration, including branching, merging, looping, and skip connections. This flexibility
allows for the construction of sophisticated architectures tailored to specific tasks. NN architectures built
using NetGraph are represented as directed graphs, where nodes represent layers or operations, and edges
represent the flow of data between them.
• A crucial step in NN construction is initializing the network's parameters. We discuss NetInitialize, a
function in Mathematica that initializes these parameters, setting the stage for efficient training. Mathematica
provides various initialization methods that can be specified through options in NetInitialize. These
methods include "Random", "Xavier", "He", and custom initialization functions.
• To quantify the performance of our NN models, we introduce loss functions. MeanSquaredLossLayer and
MeanAbsoluteLossLayer are commonly used for regression tasks, measuring the difference between
predicted and actual values. For classification problems, we explore the CrossEntropyLossLayer, a widely
used loss function that measures the dissimilarity between predicted and actual class distributions.
• Finally, we conclude by discussing NetTrain, an essential function in Mathematica for training NNs. Under
the hood, NetTrain employs gradient descent optimization algorithms, such as "SGD","ADAM" or
"RMSProp" and "SignSGD", to update the parameters of the NN iteratively.
Throughout this chapter, we provide insights and practical examples to empower readers in harnessing the
capabilities of Mathematica for constructing, training, and fine-tuning NNs for various machine learning tasks.
134
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Unit 4.1
Building Neural Network from Scratch with Mathematica
and Universal Approximation Theorem
In this unit, let us leverage Mathematica's powerful features to implement a NN from scratch, train it on a regression
task, perform forward and backward propagation, and visualize the training process and results. Implementing a NN
from scratch is an invaluable exercise for deepening your understanding of how NNs work. By building a NN from
the ground up, you gain insights into the inner workings of the algorithms involved, including forward and backward
propagation, gradient descent optimization, weight initialization, AFs, and more. Building a NN from scratch helps
you develop strong debugging skills. When you encounter errors or unexpected behavior, you'll learn to diagnose and
fix issues by tracing through the code and understanding how each component interacts.
Mathematica code 4.1 serves as an educational tool to implement the theoretical equations involved in training a NN
for regression tasks. It is implementing a NN to approximate the function 𝑓(𝑥, 𝑦) = 𝑥 2 + 𝑦 2 . By implementing these
theoretical equations in a practical coding environment, the code enables you to gain hands-on experience with training
NNs.
The code demonstrates how to perform forward propagation through the NN layers. It illustrates the calculation of
pre-activation and post-activation values for each layer, showcasing how information flows through the network.
Backpropagation, which involves computing gradients of the loss function with respect to the weights and biases of
each layer, is a fundamental aspect of training NNs. The code meticulously calculates these gradients, enabling you
to understand the mathematics behind backpropagation.
1. Generate a set of training data points by evaluating the function 𝑓(𝑥, 𝑦) over a range of 𝑥 and 𝑦 values.
2. Define the architecture of the NN with three layers: an input layer with two neurons (for 𝑥 and 𝑦), two hidden
layers with 10 neurons each, and an output layer with one neuron.
3. Initialize weights and biases randomly for each layer of the NN.
4. Define the hyperbolic tangent (tanh) AF and its derivative for use in the NN.
5. Implement forward propagation to compute the outputs of each layer in the NN for a given set of input data.
6. Plot 3D plots for the training data and the output of the NN before training. Also, create histograms to
visualize the distributions of outputs from each layer of the NN before training.
7. Define the mean squared error (MSE) loss function to quantify the difference between the predicted outputs
of the NN and the actual outputs.
8. Set the learning rate and the number of epochs for training the NN.
9. Iterate through the training data for the specified number of epochs. In each epoch:
▪ Perform forward propagation to compute the outputs of each layer.
▪ Calculate the loss using the defined loss function.
▪ Perform backpropagation to compute gradients of the loss with respect to the weights and biases of
each layer.
▪ After computing gradients, the weights and biases of each layer are updated using gradient descent
to minimize the loss function.
▪ The training loop continues until a stopping criterion is met. In this case, the loop stops either when
the specified number of epochs is reached or when the loss falls below a certain threshold (0.0001
in this code).
135
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
10. The training progress is monitored by recording the loss at each epoch. This information is used to create a
plot showing how the loss decreases over epochs, providing insight into the training performance.
11. Plot 3D plots for the training data and the output of the NN after training. Also, create histograms to visualize
the distributions of outputs from each layer of the NN after training.
12. The code utilizes matrix-matrix multiplication for both forward and backward propagation. In forward
propagation, it performs the matrix multiplication operation between the input matrices, typically
representing the input features and weights of a neural network layer, to produce the output activations. These
activations are then passed through AFs to compute the final output of the layer.
13. During backward propagation, the code computes the gradients of the loss function with respect to the input
matrices using the chain rule of calculus. It propagates the gradients backwards, adjusting the weights of the
network based on the computed gradients to minimize the loss.
While the code implements a basic FFNN and performs adequately for this simple function approximation task, there
are several potential improvements that could be made, such as experimenting with different network architectures,
AFs, learning rates, and optimization algorithms to improve training performance and convergence speed. Next
chapters will provide an in-depth exploration of these subjects.
In Mathematica, Mathematica code 4.1 can be significantly condensed using Mathematica's framework, reducing it to
just a few lines, see Mathematica code 4.2. Units 4.2-4.6 will delve into the extensive capabilities of Mathematica's
NN framework, which offers a rich array of functions and tools for the precise definition, efficient training, and
seamless deployment of NNs. The Wolfram Language offers advanced capabilities for the representation,
construction, training and deployment of NNs. A large variety of layer types is available for symbolic composition
and manipulation. Thanks to dedicated encoders and decoders, diverse data types such as image, text and audio can
be used as input and output, deepening the integration with the rest of the Wolfram Language. It combines ease of use
with advanced capabilities, making it suitable for both beginners and experts in deep learning.
(* Create training data by evaluating the function for all combinations of x and
y:*)
136
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Table[
{x,y,f[x,y]},
{x,xValues},
{y,yValues}
],1];
SeedRandom[123];
(* Dim of weights1={n1,n0}: *)
weights1=RandomVariate[NormalDistribution[0,1],{n1,n0}] ;
(* Dim of biases1={n1,1}: *)
biases1=Transpose[{RandomVariate[NormalDistribution[0,1],n1]}];
(* Dim of biasesmatrix1={n1,m}: *)
biasesmatrix1=Transpose[Table[Flatten[biases1],m]];
(* Dim of weights2={n2,n1}: *)
weights2=RandomVariate[NormalDistribution[0,1],{n2,n1}] ;
(* Dim of biases2={n2,1}: *)
biases2=Transpose[{RandomVariate[NormalDistribution[0,1],n2]}];
(* Dim of biasesmatrix2={n2,m}: *)
biasesmatrix2=Transpose[Table[Flatten[biases2],m]];
(* Dim of weights3={n3,n2}: *)
weights3=RandomVariate[NormalDistribution[0,1],{n3,n2}] ;
(* Dim of biases3={n3,1}: *)
biases3=Transpose[{RandomVariate[NormalDistribution[0,1],n3]}];
(* Dim of biasesmatrix3={n3,m}: *)
biasesmatrix3=Transpose[Table[Flatten[biases3],m]];
137
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
(* Define the vectorized (matrix) forward propagation function for all training
examples: *)
forwardPropagation[inputs_]:=Module[
{preActivlayer1,postActivlayer1,preActivlayer2,postActivlayer2,preActivlayer3,post
Activlayer3},
{preActivlayer1,postActivlayer1,preActivlayer2,postActivlayer2,preActivlayer3,post
Activlayer3}
];
(* Create the neural network output data without training (Dim of NNOutPutData
={m,3}): *)
NNOutPutData=Transpose[Join[inputData,layer3Output]];
(* Create histograms for first, second and output layers before training: *)
Table[
Histogram[
Flatten[layer[[2]]],
Automatic,
"Probability",
PlotLabel->Style[Row[{"Histogram of ",layer[[1]]}]],
FrameLabel->{"Output","Probability"},
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->250
],
{layer,
138
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
{
{"the first Hidden Layer \n Output before training",layer1Output},
{"the second Hidden Layer \n Output before training",layer2Output},
{"Output Layer \n before training",layer3Output}
}
}
]
(* Training parameters: *)
learningRate=0.1;
numEpochs=1000;
(* Training loop: *)
Do[
(* Forward propagation: *)
{preActivlayer1,layer1Output,preActivlayer2,layer2Output,preActivlayer3,layer3Outp
ut}=forwardPropagation[inputData];
(* Calculate loss: *)
currentLoss=mseLoss[outputData,layer3Output];
(* Backpropagation: *)
139
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
lastEpoch=epoch;
trainingprogress[epoch]={epoch,currentLoss};
If[currentLoss<0.0001,Break[]];,
{epoch,numEpochs}
];
ListPlot[
Table[trainingprogress[i],{i,1,lastEpoch}],
PlotLabel->"Training Progress",
AxesLabel->{"Epoch","Loss"},
Joined->True,
ColorFunction->"Rainbow",
ImageSize->220
]
(* Create 3Dplot for the trainingData and the output layer after training: *)
Table[
ListPlot3D[
data[[2]],
PlotLabel->Style[Row[{"3D plot for the ",data[[1]]}]],
ColorFunction->"Rainbow",
ImageSize->220
],
{data,{
{"training Data \n after training",trainingData},
{"output layer after training \n after training",NNOutPutDatan}
}}
]
140
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
ImageSize->250
],
{layer,{
{"First Hidden Layer \n Output after training",layer1Outputn},
{"second Hidden Layer \n Output after training",layer2Outputn},
{"Output Layer \n after training",layer3Outputn}
}
}
]
Output
Output
Output
Output
141
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
Output
142
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Comparing SGD and Full batch Gradient Descent (FBGD) provides insights into their respective strengths and
weaknesses. The goal of the Mathematica Code 4.3 and Mathematica Code 4.4 are to implement FBGD and SGD,
respectively, for linear regression using basic NN with a single neuron, one input, and one bias term.
1. Define a cost function that measures the squared error between the predicted values and the actual values of
the dataset.
2. Define the gradient of the cost function with respect to the model parameters (weights and bias) using the
chain rule of differentiation.
3. Implement a FBGD algorithm that updates the model parameters using the gradients computed over the entire
dataset at each iteration.
4. Visualize the linear regression model fitted to the dataset after running FBGD. This includes plotting the
dataset and the regression line.
5. Plot the magnitude of the gradients over the iterations to observe the convergence behavior of the
optimization algorithm.
6. Plot the gradients of the cost function with respect to the model parameters (weights and bias) over the
iterations to understand how they change during optimization.
7. Plot the value of the cost function over the iterations to monitor the optimization progress and convergence.
8. Plot the values of the model parameters (weights and bias) over the iterations to observe how they change
during optimization.
In comparison to SGD, Mathematica Code 4.4, which updates the model parameters using gradients computed from
individual data points randomly sampled from the dataset, FBGD computes gradients using the entire dataset,
Mathematica Code 4.3. This fundamental difference in sampling methodology leads to distinct convergence behaviors
between the two optimization algorithms.
For example, the figure "Cost Function over 1000 Iterations", Mathematica Code 4.3, for FBGD typically shows
smoother convergence compared to SGD, Mathematica Code 4.4, where the cost function tends to exhibit more
fluctuations due to the randomness in selecting individual data points for computing gradients. While SGD can
sometimes converge faster due to more frequent parameter updates, FBGD often provides more stable convergence
and a smoother decrease in the cost function. However, FBGD may be computationally more expensive since it
requires processing the entire dataset at each iteration.
In FBGD, the entire training dataset is used to compute the gradient of the cost function in each iteration. As a result,
the cost function surface remains static throughout the training process since the gradient is calculated using all data
points at once. Therefore, the plot displays a single static error surface. On the other hand, for SGD, only a single data
point is used to compute the gradient in each iteration. This leads to more stochastic updates of the parameters and
hence, a dynamic error surface (many error surfaces).
When visualizing various aspects such as magnitude of the gradient, evolution of weights and biases, cost function
dynamics, and parameter values over iterations, FBGD consistently exhibits smoother curves compared to SGD.
Conversely, SGD's reliance on stochastic updates often manifests in curves with more pronounced fluctuations and
variability.
143
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
parameter values over iterations, the code offers insights into the training
process, enabling an understanding of how the model learns to make predictions
based on input data: *)
(* Define the gradient of the cost function using one data point: *)
costGradient[x_,y_,w_,b_]=D[costFunction[x,y,w,b],{{w,b}}];
{w=initialGuess[[1]],b=initialGuess[[2]],n=Length[data],gradientList={},costList
={},wValues={},bValues={}},
Do[
(* Define the gradient of the cost function using full batch data: *)
gradients=(1/Length[data])*Total[costGradient[#[[1]],#[[2]],w,b]&/@data];
gradientList=Append[gradientList,gradients];
(* Values of w and b: *)
w-=learningRate*gradients[[1]];
b-=learningRate*gradients[[2]];
AppendTo[wValues,w];
AppendTo[bValues,b];
144
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
ListPlot[
data,
PlotStyle->Red,
PlotLegends->Placed[{"Data"},{0.55,0.1}],
ImageSize->250
],
Plot[finalW*x+finalB,
{x,0,10},
PlotStyle->Blue,
PlotLegends->Placed[{"Regression Line"},{0.55,0.1}],
ImageSize->250
],
Frame->True,
FrameLabel->{"x","y"},
PlotLabel->"Full Batch Gradient Descent Linear Regression"
]
145
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Frame->True,
FrameLabel->{"Iterations","Values"},
PlotLegends->Placed[{"Value of w","Value of b"},{0.75,0.4}],
PlotLabel->"Values of w and b over 1000 Iterations",
ImageSize->250
]
Output
Output
146
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
Output
Output
147
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
{w=initialGuess[[1]],b=initialGuess[[2]],n=Length[data],gradient,x,y,gradientLi
st,costList,wValues,bValues},
gradientList={};
costList={};
wValues={};
bValues={};
Do[
{x,y}=RandomChoice[data];
gradient=costGradient[x,y,w,b];
gradientList=Append[gradientList,gradient];
w-=learningRate*gradient[[1]];
b-=learningRate*gradient[[2]];
AppendTo[wValues,w];
AppendTo[bValues,b];
cost=costFunction[x,y,w,b];
costList=Append[costList,cost],
{iterations}
];
{w,b,gradientList,costList,wValues,bValues}
];
148
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
(* 3D plot of mean squared error surfaces for 11 data points with respect to w
and b: *)
ListPlot3D[
errors,
ImageSize->250,
PlotLabel->"Cost Function Surfaces",
PlotStyle->Directive[Opacity[0.4]],
PlotRange->Full
]
149
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
150
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
Output
Output
151
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output {{4,7},{18,40},{{4,7},{10,15}},{18,40}}
Output {{5,9},{26,55},{{4,7},{10,15}},{26,55}}
(* Define the sigmoid function with a steep slope and a shift parameter *)
sigmoid[x_,a_,b_]:=1/(1+Exp[a x+b])
152
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
(* Define the rectangular towers function by subtracting the two sigmoid functions
*)
rectangularTowers[x_]:=sigmoidLeft[x]-sigmoidRight[x]
Plot[
rectangularTowers[x],
{x,-5,5},
PlotRange->All,
AxesLabel->{"x","y"},
PlotLabel->"Tower Function",
ImageSize->200,
PlotStyle->Red
]
Plot[
sigmoidLeft[x],
{x,-5,5},
PlotRange->All,
AxesLabel->{"x","y"},
PlotLabel->"Sigmoid Left",
ImageSize->200,
PlotStyle->Blue
]
Plot[
sigmoidRight[x],
{x,-5,5},
PlotRange->All,
AxesLabel->{"x","y"},
PlotLabel->"Sigmoid Right",
ImageSize->200,
PlotStyle->Blue
]
Output
Output
153
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
154
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
155
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
156
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
(* Helper function to create a 3D plot with the given function and label: *)
createPlot3D[func_,{x_,xMin_,xMax_},{y_,yMin_,yMax_},plotLabel_]:=Plot3D[
func,
{x,xMin,xMax},
{y,yMin,yMax},
157
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Evaluate@Append[
commonPlotSettings,
PlotLabel->plotLabel
]
]
158
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
159
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Unit 4.2
Layers: LinearLayer and ElementwiseLayer
LinearLayer
A LinearLayer represents a fully connected layer where each neuron in the layer is connected to every neuron in the
preceding layer. When you use a LinearLayer, you're effectively introducing a set of neurons in your NN, each
performing a linear transformation on the input data.
LinearLayer[n]
represents a trainable, fully connected net layer that computes 𝑾 ∙ 𝒙 + 𝒃 with output vector of size n.
LinearLayer[{n1,n2,…}]
represents a layer that outputs an array of dimensions n1×n2×….
LinearLayer[]
leaves the dimensions of the output array to be inferred from context.
LinearLayer[n,opts]
includes options for initial weights and other parameters.
• When you create a NN layer in Mathematica using LinearLayer and don't specify weights and biases
explicitly, they are automatically generated when you initialize the network using NetInitialize or train it
using NetTrain.
• "Biases"->None: This setting is used to explicitly specify that biases should not be used in the layer.
• When you apply a LinearLayer to input data, LinearLayer[…][input], it computes the output by applying
the learned weights and biases (if any) to the input data.
• If you provide a list of inputs {input1, input2, ...} to a LinearLayer, it computes the outputs for each
of these inputs separately.
• The NetExtract function in Mathematica can be used to extract specific parts (such as weights and biases)
from a trained NN. For a LinearLayer object, you can use NetExtract to retrieve its weights and biases.
• If you specify LinearLayer[{}], it indicates that the LinearLayer should produce a single real number as
output. This is useful in scenarios where you want the output of the layer to be a scalar value.
• LinearLayer[n, "Input"->m]: This is indeed a common usage pattern for LinearLayer. It represents a
linear layer that takes a vector of length m as input and produces a vector of length n as output. This is a
fundamental building block in many NN architectures, where fully connected layers transform input vectors
into output vectors.
• In larger NN architectures, sometimes the input shape of a specific layer cannot be inferred from previous
layers. In such cases, you can use the "Input"->shape option with LinearLayer to fix the input shape. The
160
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
shape parameter can take various forms to specify the input shape, allowing you to define the structure of the
network more explicitly.
• Note that the layers containing learnable parameters appear in red, indicating that they require initial values
before the net can be applied to an input.
"Real" a single real number
m a vector of length m
Output
161
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output {
{0.220028,0.802785,0.734378},
{0.0580037,0.538777,0.423361},
{0.525993,0.0475469,0.498489}
}
Output {
{4.52873,8.3003},
{2.90564,4.46607},
{2.61655,4.33264}
}
Output
Output {
{0.590603,0.384391,0.635673},
{0.974991,0.950379,0.485747}
}
Output {
{3.2664,8.0984},
{4.33299,11.5663}
}
Output
162
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output {
{1.,2.,3.},
{4.,5.,6.}
}
(* Initialize the LinearLayer with random weights and biases using NetInitialize:
*)
randomlyInitializedLinearLayer=NetInitialize[uninitializedLinearLayer]
Output
Output
Output {
{0.9754,0.276369},
{0.0588502,0.681333}
}
Output {
{-0.364402,-0.799045,1.58972},
{-0.0551678,0.673965,-0.522975}
}
163
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
(* Manually compute the same result using the defined linear function: *)
linearResult=linear[
data,
NetExtract[layer,"Weights"]//Normal,
NetExtract[layer,"Biases"]//Normal
]
Output
Output {-3.75531,14.955}
Output {-3.75531,14.955}
164
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
ElementwiseLayer
ElementwiseLayer[f]
represents a net layer that applies a unary function f to every element of the input array.
ElementwiseLayer["name"]
applies the function specified by "name".
• The function f can be any one of the following: Ramp, LogisticSigmoid, Tan, Tanh, ArcTan, ArcTanh,
Sin, Sinh, ArcSin, ArcSinh, Cos, Cosh, ArcCos, ArcCosh, Cot, Coth, ArcCot, ArcCoth, Csc, Csch,
ArcCsc, ArcCsch, Sec, Sech, ArcSec, ArcSech, Haversine, InverseHaversine, Gudermannian,
InverseGudermannian, Log, Exp, Sqrt, CubeRoot, Abs, Gamma, LogGamma, Erf, InverseErf, Erfc,
InverseErfc, Round, Floor, Ceiling, Sign, FractionalPart, IntegerPart, Unitize,
KroneckerDelta.
• In general, f can be any object that when applied to a single argument gives any combination of Ramp,
LogisticSigmoid, etc., together with numbers, Plus, Subtract, Times, Divide, Power, Surd, Min, Max,
Clip, Mod, Threshold, Chop and some logical operations using If, And, Or, Which, Piecewise, Equal,
Greater, GreaterEqual, Less, LessEqual, Unequal, Negative, NonNegative, Positive,
NonPositive, PossibleZeroQ.
• ElementwiseLayer supports the following values for "name":
"Swish" x LogisticSigmoid[x]
"HardSwish" x Min[Max[x+3,0],6]/6
"Mish" x Tanh[Log[1+Exp[x]]]
"SoftSign" x/(1+Abs[x])
"SoftPlus" Log[Exp[x]+1]
"HardTanh" Clip[x,{-1,1}]
"Sigmoid" LogisticSigmoid[x]
165
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output {-0.995055,-0.964028,-0.761594,0.,0.761594,0.964028,0.995055}
Output
166
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output {-1.,-1.,-1.,0.,1.,1.,1.}
Output
167
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output {0.,0.,0.,0.,1.,2.,3.}
Output
Output {1.,2.,3.}
Output {
{1.,2.,3.},
{0.,0.,0.}
}
168
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
{i,1,Length[range]}
];
(* Plot the results using ListPlot: *)
ListPlot[
data,
ImageSize->250,
PlotRange->All,
AxesLabel->{"Input","Output"},
PlotLabel->"ElementwiseLayer Example"
]
Output
Output {4.71828,11.3891,26.0855}
169
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output {
{Input Array:},
{({
{-2},
{-1},
{0},
{1},
{2}
})},
{Result Array:},
{({
{-0.964028},
{-0.761594},
{0.},
{1.},
{2.}
})}
}
170
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
(* When applied, the layer will automatically thread over a batch of vectors: *)
activation[preactivation]
Output
Output {
{0.271247,0.129702,0.564545},
{0.234738,0.846121,0.799014},
{0.280505,0.54826,0.145928}
}
Output {
171
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
{2.72429,4.12077,2.70318},
{4.82402,8.96364,5.17534},
{2.31481,3.73888,3.15865}
}
Output
Output {{2.72429,4.12077,2.70318},{4.82402,8.96364,5.17534},{2.31481,3.73888,3.15865}}
customBiases=RandomReal[0,outputSize];
extractWeights=NetExtract[randomlyInitializedLinearLayer,"Weights"];
172
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
extractWeightsData=Flatten[extractWeights];
Output
Output
Output
173
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Unit 4.3
Containers: NetChain and NetGraph
In Mathematica, NNs are typically built by combining multiple layers together to form a network architecture. While
a single NN layer can perform basic transformations on its input data, it's usually not sufficient for more complex
tasks. By combining multiple layers together, you can create deeper and more powerful NNs capable of learning
intricate patterns and making more accurate predictions.
• The NetChain container is commonly used to chain layers together sequentially, where the output of one
layer serves as the input to the next layer. This sequential structure is suitable for many standard NN
architectures.
• However, there are cases where you may need more complex connectivity patterns between layers. For
example, you may want to create skip connections, recurrent connections, or other non-sequential
connections within the network. In such cases, the NetGraph container is more appropriate. NetGraph allows
you to define a graph-like structure where nodes represent different layers or operations, and edges represent
the flow of data between them. This flexibility enables you to construct a wide variety of NN architectures
tailored to your specific needs.
NetChain
NetChain[{layer1,layer2,…}]
specifies a neural net in which the output of layer i is connected to the input of layer i+1.
NetChain[<|"name1"->layer1,"name2"->layer2,…|>]
specifies a net consisting of a chain of explicitly named layers.
• The input data is provided to the NetChain, and it is passed into the first layer specified in the chain. The
input data then undergoes sequential processing through each layer in the chain, with the output of one layer
serving as the input for the next layer. The final output of the NetChain is taken from the output of the last
layer in the chain, providing the result of the network's computation.
• If the first layer has multiple input ports or the last layer has multiple output ports, the NetChain will have
the same input or output ports respectively, allowing for more complex network architectures.
• NetChain[…][data] gives the result of applying the net to data.
• Normal[NetChain[…]] returns a list or association of the layers used to construct the chain.
• NetChain[…][[spec]] extracts the layer specified by spec from the net. This enables users to access and
manipulate individual layers within the network.
• The StandardForm of NetChain provides a summary of the layers in the chain, along with the array
dimensions of the output of each layer. Clicking on a layer in the chain reveals more detailed information
about that specific layer, aiding in network inspection and debugging.
• Note that the layers containing learnable parameters appear in red, indicating that they require initial values
before the net can be applied to an input.
• The overall input and output array shapes for the chain can be explicitly specified using the "Input"->shape
and "Output"->shape options for NetChain, providing more control over the network's input and output
dimensions.
Possible forms for shape include:
174
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
• Any lengths ni given as Automatic are inferred from the structure of the chain, simplifying network
construction by automatically determining certain dimensions based on the network's architecture.
• NetChain[…][data,...,opts] specifies that options should be used when applying the network to data,
allowing for additional customization during network evaluation. Possible options include: BatchSize,
NetEvaluationMode, RandomSeeding, TargetDevice and WorkingPrecision.
• EdgeList[NetChain[…]] returns the list of connections in the network, providing insights into the network's
connectivity and structure.
• net[data,NetPort[oport]] can be used to obtain the value of the net at oport when it is applied to the
specified data. oport must refer to an output port, a subnet of the net, or a layer.
net=NetChain[
{
LinearLayer[3],(* Linear layer with 3 output nodes.*)
ElementwiseLayer[Tanh],(* Tanh activation function.*)
LinearLayer[1](* Linear layer with 1 output node.*)
},
"Input"->4
]
Output
175
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
Output
NetChain[{3,Tanh,4,Ramp,5}]
Output
net=NetChain[{1,Ramp,2,Tanh}]
Normal[net]
176
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
{ ,
(* Create a NetChain: *)
net=NetChain[
{
ElementwiseLayer[Tanh],
ElementwiseLayer[Cos],
ElementwiseLayer[Sin]
}
]
(* Obtain the output of the first layer of the net when applied to data: *)
177
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
net[{-1.2,3.1},NetPort[1,"Output"]]
(* Values extracts the numerical values of all outputs obtained in the previous
step: *)
Values[net[{-1.2,3.1},NetPort[All,"Output"]]]
Output
Output {-0.833655,0.995949}
Output {-0.833655,0.995949}
Output <|NetPort[{1,Output}]->{-0.833655,0.995949},NetPort[{2,Output}]-
>{0.672174,0.543706}|>
Output <|NetPort[{1,Output}]->{-0.833655,0.995949},NetPort[{2,Output}]-
>{0.672174,0.543706},NetPort[{3,Output}]->{0.622689,0.517311}|>
Output {{-0.833655,0.995949},{0.672174,0.543706},{0.622689,0.517311}}
(* Construct a chain consisting of three layers and specify that the input is a
length "inputSize" vector: *)
neuralNetwork=NetChain[
{
LinearLayer[3,"Biases"->None],
ElementwiseLayer[Tanh],
178
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
LinearLayer[1,"Biases"->None]
},
"Input"->inputDimension
]
(* Initialize the net with random weights, making it ready for training or
evaluation: *)
neuralNetwork=NetInitialize[neuralNetwork]
outputFirstLayer=firstLayer[inputData];
outputSecondLayer=secondLayer[outputFirstLayer];
outputThirdLayer=thirdLayer[outputSecondLayer];
179
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
outputSecondLayerNetPort=outputOfAllLayers[[All,2]];
outputThirdLayerNetPort=outputOfAllLayers[[All,3]];
(* Create histograms for the output data of each layer using NetPort: *)
Table[
Histogram[
Flatten[layer[[2]]],
Automatic,
"Probability",
PlotLabel->Style[Row[{"Histogram of Output Data (NetPort):",layer[[1]]}]],
AxesLabel->{layer[[1]],"Probability"},
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->300
],
{layer,{
{"FirstLayer ",outputFirstLayerNetPort},
{"SecondLayer",outputSecondLayerNetPort},
{"ThirdLayer",outputThirdLayerNetPort}
}
}
]
Output
Output
180
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
Output
Output
Output {{-0.359447,-0.0499231},{-1.12706,1.08654},{1.89365,-0.93114}}
Output {{-0.631947,0.082531,0.06014}}
Output
181
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
NetGraph
NetGraph[{layer1,layer2,…},{m1->n1,m2->n2,…}]
specifies a neural net defined by a graph in which the output of layer mi is given as input to layer ni.
NetGraph[<|"name1"->layer1,"name2"->layer2,… ->,{"namem1"->"namen1",…}]
specifies a net with explicitly named layers.
NetGraph[layer]
converts a layer or a NetChain into an equivalent minimal NetGraph.
• In Mathematica, NetGraph is a powerful function used for building and representing complex NN
architectures as directed acyclic graphs (DAGs). It allows for combining various NN layers and operations
• When constructing a NetGraph in Mathematica, you can create input or output ports for the entire graph by
specifying NetPort["input"]-> or ->NetPort["output"] respectively in the list of connections.
• In Mathematica’s NetGraph, you can specify a linear chain of connections within the graph using the syntax
layer1 -> layer2 -> ... -> layerN. This notation establishes a sequential connection between each
layer, where layer1 is connected to layer2, layer2 is connected to layer3, and so on, until layerN. This linear
182
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
chain notation is useful for defining simple feedforward architectures or for building blocks of more complex
networks, such as CNNs or RNNs.
• If the nth layer, or a layer named "layer", has more than one input or output port, you can disambiguate them
by using the syntax NetPort[n, "port"] or NetPort["layer", "port"]. By using NetPort with the
appropriate layer index or name, you can explicitly specify which input or output port of a layer you want to
connect in the NetGraph, allowing for greater control and flexibility in designing complex NN architectures.
• If you leave one or more input or output ports of any layers unconnected within a NetGraph, they will
automatically become ports of the entire NetGraph. This behavior allows for more flexibility in connecting
multiple NetGraph instances or integrating them into larger network architectures. This behavior facilitates
the construction of more modular and reusable network architectures in Mathematica, allowing you to easily
combine different components or subnetworks into larger and more complex models.
• In Mathematica's NetGraph, you can mute some output ports of layers by setting them to None. This is
particularly useful when you want to disable certain outputs of a layer within the graph.
• If the NN (NetGraph) has a single input port, you can directly apply the network to input data using the
syntax NetGraph[...][data]. This applies the network to the input data and produces the output.
• If the network has multiple input ports, you provide data to each port using an association syntax like
NetGraph[...] [<|port1 -> data1, ... |>]. This allows you to specify input data for each input port
individually.
• If the network has a single output port, you can still use the syntax NetGraph[...][data] to obtain the
output. The output will be the result for that single output port.
• For a net with multiple output ports, NetGraph[…][data] gives an association of the outputs for all ports.
• The StandardForm of NetGraph shows the connectivity of layers in the graph and annotates edges with the
dimensions of the array that the edge represents. Clicking a layer or a port in the graph shows more
information about that layer or port.
• Normal[NetGraph[…]] returns a list or association of the layers used to construct the graph.
EdgeList[NetGraph[…]] returns the list of connections in the graph.
• NetGraph[…][[spec]] extracts the layer specified by spec from the net.
NetPort
NetPort["port"]
represents the specified input or output port for a complete net.
NetPort[{n,"port"}]
represents the specified port for layer number n in a NetGraph or similar construct.
NetPort[{"name","port"}]
represents the specified port for the layer with the specified name.
chain=NetChain[{2,Tanh,3,Ramp}]
NetGraph[chain]
Output
183
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
NetGraph[{2,Ramp,4,Ramp,1},{1->2->3->4->5}]
Output
184
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
NetGraph[<|
"linear1"->2,
"ramp1"->Ramp,
"linear2"->2,
"ramp2"->Ramp
|>,
{"linear1"->"ramp1"->"linear2"->"ramp2"}
]
Output
Output
185
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
Output
Output
{ , ,
, }
186
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
net=NetGraph[
{
(* ReLU activation: *)
LinearLayer[20],Ramp,
(* Exponential activation: *)
LinearLayer[3],Exp,
(* Sine activation: *)
LinearLayer[2],Sin,
(* Cosine activation: *)
LinearLayer[1],Cos
},
{1->2->3->4->5->6->7->8->9->10->11->12}]
Output
(* The code constructs a neural network graph using Mathematica's NetGraph function.
It consists of five layers, where the first and third layers each have three neurons
and the second and fourth layers apply the Ramp activation function. The fifth
layer performs addition. Input data is supplied through a port named "Input".
Connections between layers are established such that the output of the first layer
is connected to the input of the second layer, the output of the third layer is
connected to the input of the fourth layer, and the input port "Input", along with
the outputs of the second and fourth layers, is connected to the fifth layer. This
architecture enables the network to perform an operation requiring three inputs and
produce an output based on their combination: *)
NetGraph[
(*Define the layers of the net graph: *)
{3,Ramp,3,Ramp,Plus},
(* The output of the third layer is connected to the input of the fourth layer:
*)
187
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
3->4,
(* The input port named "Input", along with the outputs of the second and
fourth layers, are all connected to the fifth layer using curly braces {}: *)
{NetPort["Input"],2,4}->5
}
]
Output
(* The NetGraph constructs a neural network with multiple input ports, featuring
five layers. The first and third layers consist of three neurons each, while the
second and fourth layers apply the Ramp activation function. The fifth layer
performs addition. Input data is supplied through three different input ports
labeled "Input1","Input2", and "Input3". Connections between layers are established
such that "Input1" is connected to the first layer, "Input2" to the third layer,
and "Input3" is jointly connected with the output of the second and fourth layers
to the fifth layer. This architecture enables the network to process multiple inputs
simultaneously, incorporating them into the network's operations before producing
an output: *)
NetGraph[
(* Define the layers of the net graph: *)
{3,Ramp,3,Ramp,Plus},
(* Connects "Input2" port to the third layer (index 3), and output of the third
layer to the fourth layer (index 4): *)
NetPort["Input2"]->3->4,
(*Connects "Input3" port and output of the second layer (index 2), and output
of the fourth layer (index 4) to the fifth layer (index 5): *)
{NetPort["Input3"],2,4}->5
}
]
188
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
(* Connects "Input" port and output of the second layer to the third layer, and
then connects the output of the third layer to "Output2" port: *)
{NetPort["Input"],2}->3->NetPort["Output2"],
189
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Unit 4.4
NetInitialize
NetInitialize[net]
gives a net in which all uninitialized learnable parameters in net have been given initial values.
NetInitialize[net,All]
gives a net in which all learnable parameters have been given initial values.
• In Mathematica, the NetInitialize function initializes the parameters of a NN (net) before it's used for
computation. When NetInitialize[net, All] is used, it initializes all parameters, including those that are
learnable or trainable.
• However, it's essential to note that when you initialize the network using NetInitialize[net, All], any
existing training or preset learnable parameters in net will indeed be overwritten by the newly initialized
parameters. This means that if the network had been previously trained or had preset learnable parameters
defined, they will be discarded and replaced with newly initialized parameters.
• In NN initialization, especially when using NetInitialize in Mathematica, weights are typically initialized
with random values, and biases are usually initialized to zero.
• This approach is commonly used because it helps introduce some level of randomness into the network's
initial weights, which can aid in breaking symmetry and preventing the network from getting stuck in local
minima during training. Random initialization also helps in exploring the solution space more effectively.
• On the other hand, biases are often initialized to zero because they represent the additive constants in the
linear transformation of the network's inputs. Initializing biases to zero ensures that the network starts with a
neutral bias before it learns the optimal bias values during training.
• However, it's worth noting that there are variations and alternatives to these initialization strategies, and
different initialization schemes may be more appropriate for different types of networks or tasks. For
example, in certain cases, weights may be initialized using specific distributions or scaling techniques to
better suit the network architecture or the nature of the data being processed.
For the methods "Kaiming" and "Xavier", the following suboption is supported:
"Distribution" "Normal" either "Normal" or "Uniform"
190
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Histogram[
Flatten@NetExtract[net,"Biases"],
Automatic,
"Probability",
PlotLabel->"Histogram of Biases",
AxesLabel->{"Biases","Probability"},
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->250
]
Output
Output
191
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
(* The following two lines demonstrate the default behavior of NetInitialize, where
the same random seed (1234) is used for repeated calls to initialize a linear layer
with one neuron and one input dimension: *)
Normal@NetExtract[NetInitialize[LinearLayer[1,"Input"->1]],"Weights"]
Normal@NetExtract[NetInitialize[LinearLayer[1,"Input"->1]],"Weights"]
(* The next two lines show the use of RandomSeeding->Automatic when initializing
the network. This ensures that repeated calls to initialize the network produce
different initializations by using different random seeds:*)
Normal@NetExtract[NetInitialize[LinearLayer[1,"Input"->1],RandomSeeding-
>Automatic],"Weights"]
Normal@NetExtract[NetInitialize[LinearLayer[1,"Input"->1],RandomSeeding-
>Automatic],"Weights"]
Output {{-0.508336}}
Output {{-0.508336}}
Output {{-1.22817}}
Output {{-0.590982}}
(* Construct a base network that takes vector inputs of size 2 and produces
vector outputs of size 1:*)
net=NetChain[
{30,Sin,3,Tanh,3,LogisticSigmoid,1},
"Input"->2
];
192
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
NetInitialize[
net,
Output
193
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Manipulate[
Module[
{initializedNet,inputData,layer1,layer2,layer3,layer4,layer5,outputlayer1,output
layer2,outputlayer3,outputlayer4,outputlayer5,simpleNet,histogramWeights,histogr
amOutputs},
194
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
{layer1,layer2,layer3,layer4,layer5}=Table[NetExtract[initializedNet,j],{j,1,5}]
;
outputlayer1=layer1[inputData];
outputlayer2=layer2[outputlayer1];
outputlayer3=layer3[outputlayer2];
outputlayer4=layer4[outputlayer3];
outputlayer5=layer5[outputlayer4];
histogramWeights=Table[
Histogram[
Flatten@NetExtract[initializedNet,{i,"Weights"}],
Automatic,
"Probability",
PlotLabel->StringForm["Histogram of Weights layer ``",i],
AxesLabel->{"Weights","Probability"},
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->250
],
{i,{1,3}}
];
histogramOutputs=Table[
Histogram[
Flatten[i[[2]]],
Automatic,
"Probability",
PlotLabel->Style[Row[{"Histogram for Data of ",i[[1]]}]],
AxesLabel->{i[[1]],"Probability"},
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->250
],
{i,{{"outputlayer2",outputlayer2},{"outputlayer4",outputlayer4}}}
];
Column[{histogramWeights,histogramOutputs}]
],
{{seed,123,"Random Seed"},1,1000,1,Appearance->"Labeled"},
{{weights,1,"Weights"},0,2,0.01,Appearance->"Labeled"}
]
195
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
196
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Unit 4.5
Cost Functions
MeanSquaredLossLayer[]
represents a loss layer that computes the mean squared loss between its "Input" port and "Target" port.
MeanAbsoluteLossLayer[]
represents a loss layer that computes the mean absolute loss between the "Input" port and "Target" port.
CrossEntropyLossLayer["Index"]
represents a net layer that computes the cross-entropy loss by comparing input class probability vectors with indices
representing the target class.
CrossEntropyLossLayer["Probabilities"]
represents a net layer that computes the cross-entropy loss by comparing input class probability vectors with target
class probability vectors.
CrossEntropyLossLayer["Binary"]
represents a net layer that computes the binary cross-entropy loss by comparing input probability scalars with target
probability scalars, where each probability represents a binary choice.
197
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output 31.6667
Output 5.
198
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
loss3[<|"Input"->inputData,"Target"->targetData|>]
loss4[<|"Input"->inputData,"Target"->targetData|>]
Output {11.,66.,171.}
Output {3.,8.,13.}
Output 82.6667
Output 8.
Output 82.6667
Output 8.
Output 82.6667
Output 8.
199
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
inputdata=RandomReal[5,20];
outputdata=RandomReal[5,20];
Output 6.18515
Output 6.18515
Output 2.15588
Output 2.15588
(* The code provides two alternative definitions for a manual mean squared loss
calculation. The first definition uses a Table construct to calculate the element-
wise mean squared loss for each pair of input and target vectors. The second
definition employs Transpose to achieve the same result in a concise manner: *)
(* Compare the output of the MeanSquaredLossLayer with "Input" port and the manual
definition on an example: *)
(* Data container with "Input" and "Target" keys: *)
data=<|"Input"->inputData,"Target"->targetData|>;
Output {11.,66.,171.}
Output {11.,66.,171.}
200
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
(* Compare the output of the MeanAbsoluteLossLayer with "Input" port and the manual
definition on an example: *)
(* Data container with "Input" and "Target" keys: *)
data=<|"Input"->inputData,"Target"->targetData|>;
201
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output 9.
Output 2.33333
Output {0.666667,2.,18.75}
Output {0.666667,1.,4.25}
(* Applying the networks to input data containing "Input" and "Target" keys: *)
resultNet1=net1[<|"Input"->{{1,2,3},{1,3,5},{5,2,2}},"Target"-
>{{2,1,3},{1,5,6},{3,4,2}}|>]
resultNet2=net2[<|"Input"->{{1,2,3},{1,3,5},{5,2,2}},"Target"-
>{{2,1,3},{1,5,6},{3,4,2}}|>]
Output
202
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output 6.77142
Output {1.85158,13.6991,4.76358}
(* Applying the networks to input data containing "Input" and "Target" keys: *)
resultNet1=net1[<|"Input"->{{1,2,3},{1,3,5},{5,2,2}},"Target"-
>{{2,1,3},{1,5,6},{3,4,2}}|>]
resultNet2=net2[<|"Input"->{{-1,-2,-3},{-1,-3,-5},{-5,-2,-2}},"Target"-
>{{2,1,3},{1,5,6},{3,4,2}}|>]
Output
203
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output 1.
Output {2.,4.,3.}
(* Plot the loss as the input approaches 1 when the target is fixed at 1: *)
Plot[
binaryCrossEntropyLoss[input,1],
{input,0,1},
ImageSize->250,
PlotLabel->"Binary Cross-Entropy Loss",
AxesLabel->{"Input","Loss"}
]
(* Create a contour plot to visualize loss variation with input and target values.
In general, the loss is minimized when the target approaches the input: *)
ContourPlot[
binaryCrossEntropyLoss[inputValue,targetValue],
{inputValue,0,1},
{targetValue,0,1},
Contours->10,
PlotLegends->Automatic,
PlotRangePadding->0,
FrameLabel->{"Input","Target"},
ImageSize->250,
PlotLabel->"Loss Contour Plot",
ContourStyle->{White},
204
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow"
]
Output 1.60944
Output 1.60944
Output
Output
Output
Output 1.33218
Output {1.33218,2.08286,0.325083}
205
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Unit 4.6
NetTrain
While we may not have yet completed the exhaustive theoretical groundwork necessary for training NNs, such as
exploring various optimization methods and regularization techniques, it is imperative to take our first steps in
practical application. In the realm of machine learning, theory and practice are intertwined, each informing and
enriching the other.
Building a NN using off-the-shelf software can be likened to a child constructing a toy from building blocks. In both
cases, you have distinct elements (blocks in the toy analogy, components or modules in the NN) that serve specific
purposes. These components might include layers (such as linear layers, activation layers, etc.), optimizers, loss
functions, and more in the context of NNs. Like assembling blocks, the process involves compatibility, a structured
assembly process, trial and error, iteration, and opportunities for learning and creativity. Just as a child learns spatial
reasoning and problem-solving skills through building with blocks, developers learn about NN architectures and
optimization techniques through experimentation and refinement, aiming to achieve optimal performance with their
models.
Let us begin training our networks using NetTrain in Mathematica. This process will be executed step by step.
Initially, in this section, we provide a basic introduction, based on the theoretical foundations established in previous
chapters to ensure a solid understanding. Subsequently, we will delve into more intricate details in the forthcoming
chapters.
In this section, we will explore the diverse functionalities of the NetTrain function, understanding its syntax,
parameters, and various forms.
NetTrain[net,{input1->output1,input2->output2,…}]
trains the specified neural net by giving the inputi as input and minimizing the discrepancy between the outputi and
the actual output of the net, using an automatically chosen loss function.
NetTrain[net,<|port1->{data11,data12,…},port2->{…},…|>]
trains the specified net by supplying training data at the specified ports.
NetTrain[net,"dataset"]
trains on a named dataset from the Wolfram Data Repository.
NetTrain[net,f]
calls the function f during training to produce batches of training data.
NetTrain[net,data,"prop"]
gives data associated with a specific property prop of the training session.
NetTrain[net,data,All]
gives a NetTrainResultsObject[…] that summarizes information about the training session.
206
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Remarks:
• Any input ports of the net whose shapes are not fixed will be inferred from the form of training data.
• Individual training data inputs can be scalars, vectors, numeric tensors.
• If the loss is not given explicitly using LossFunction, a loss function will be chosen automatically based on
the final layer or layers in the net.
• With the default setting of BatchSize->Automatic, the batch size will be chosen automatically, based on
the memory requirements of the network and the memory available on the target device. The maximum batch
size that will be automatically chosen is 64.
• With the default setting of MaxTrainingRounds->Automatic, training will occur for approximately 20
seconds, but never for more than 10,000 rounds.
• With the setting of MaxTrainingRounds->n, training will occur for n rounds, where a round is defined to be
a traversal of the entire training dataset.
• NetTrain[net,data,All] returns a NetTrainResultsObject[…] that contains values for all properties that
do not require significant additional computation or memory.
• NetTrainResultsObject[…][prop] is used to look up property prop from the NetTrainResultsObject.
• Properties supported include:
"ArraysLearningRateMultipliers", "BatchesPerRound", "BatchLossList",
"BatchMeasurementsLists", "BatchSize", "BestValidationRound", "CheckpointingFiles",
"ExamplesProcessed", "FinalLearningRate", "FinalPlots", "InitialLearningRate", "LossPlot",
"MeanBatchesPerSecond", "MeanExamplesPerSecond", "NetTrainInputForm",
"OptimizationMethod", "ReasonTrainingStopped", "RoundLoss", "RoundLossList",
"RoundMeasurements", "RoundMeasurementsLists", "RoundPositions", "TargetDevice",
"TotalBatches", "TotalRounds", "TotalTrainingTime", "TrainedNet", "TrainingExamples",
"TrainingNet", "ValidationExamples", "ValidationLoss", "ValidationLossList",
"ValidationMeasurements", "ValidationMeasurementsLists", and "ValidationPositions"
• If a net already contains initialized or previously trained weights, these will be not be reinitialized by
NetTrain before training is performed.
"ADAM" stochastic gradient descent using an adaptive learning rate that is invariant to diagonal rescaling of
the gradients
"RMSProp" stochastic gradient descent using an adaptive learning rate derived from exponentially smoothed
average of gradient magnitude
"SGD" ordinary stochastic gradient descent with momentum
"SignSGD" stochastic gradient descent for which the magnitude of the gradient is discarded
Suboptions for specific methods can be specified using Method->{"method",opt1->val1,…}. The following
suboptions are supported for all methods:
207
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
(* Use the trained network to predict the output for a single input value (2.1):
*)
trainednet[2.1]
(* Use the trained network to predict outputs for multiple input values {1,2,3,4}:
*)
trainednet[{1,2,3,4}]
Output
Output 6.305
Output {2.95,6.,9.05,12.1}
Output
208
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
(* Use the trained network to predict outputs for multiple input values {2,3,4,5}:
*)
multiplePredictions=trainedNetwork[{2,3,4,5}]
Output
Output {5.99999,9.04999,12.1,15.15}
(* This code creates and trains a neural network (NetGraph) with a directed graph
of layers {1,3,3,1}. The connections between layers are specified by the graph {1-
>2->3->4}. Training data, as input-output pairs, is provided in a similar manner
as the previous examples: *)
(* Define and train a neural network with a directed graph of layers {1,3,3,1}:
*)
directedGraphNet=NetTrain[
NetGraph[{1,3,3,1},{1->2->3->4}],
{1->2.9,2->6.1,3->9.0,4->12.1},
BatchSize->4,
MaxTrainingRounds->500,
LearningRate->0.001,
LossFunction->MeanSquaredLossLayer[],
Method->"SGD"
]
209
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output {5.99999,9.04999,12.1,15.15}
(* The following comments explain how the training data is represented in different
formats, including rules, lists, and associations: *)
210
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
Output
Output
211
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
{x,0,4 Pi,0.01}
];
data=Transpose[{inputs,target}];
Output
Output
212
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
(* The code aims to illustrate the training of a neural network for a regression
task on a 2D dataset, visualize the learned function, and evaluate the network's
prediction on a specific input: *)
213
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output 0.385327
Output
(* The code demonstrates how a neural network can be trained on noisy data to learn
the underlying patterns, and how the trained network can be used to make predictions
on new input data. The visualizations help in assessing the performance of the
trained network and comparing it to the noisy dataset: *)
(* Generate a dataset with input-output pairs for a 2D function with added random
noise: *)
trainingData=Flatten[
Table[
{{x,y}->Sin[x]+Cos[y]+RandomVariate[NormalDistribution[0,0.05]]},
{x,-3,3,0.2},
{y,-3,3,0.2}],
2
];
214
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
regressionNetwork,
trainingData,
MaxTrainingRounds->50
]
(* Visualization: *)
Output
Output
215
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output
Output
(* The code demonstrates how to use the NetTrainResultsObject to query and access
various training-related information after training a neural network: *)
216
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
{x,-3,3,.005},
{y,-3,3,.005}
];
Output
Output 1409
Output 1024
217
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
Output {SGD,GradientClipping->None,L2Regularization->None,LearningRate-
>0.01,LearningRateSchedule->Polynomial,Momentum->0.93,WeightClipping->None}
Output 0.01
Output 36.812
Output
Output
218
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
classificationPerceptron=NetChain[{LinearLayer[],LogisticSigmoid}];
(* Predict whether a new input belongs to the positive class (True or False): *)
predictionSingleInput=trainedPerceptron[3.5]
(* Obtain the probability of the input being True by disabling the NetDecoder: *)
probabilitySingleInput=trainedPerceptron[3.5,None]
Output
Output True
Output 0.974409
Output {False,False,False,False,True,True,True,True}
Output
219
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
trainingData=points->labels;
(* Create a network with two LinearLayer layers and a final transformation into a
probability using an ElementwiseLayer: *)
classificationNet=NetChain[
{LinearLayer[20],LinearLayer[],ElementwiseLayer[LogisticSigmoid]},
"Output"->NetDecoder["Boolean"]
]
(* Visualize the trained network's decision boundary. The net was not able to
separate the two classes: *)
(* Explain the limitations of a network with two LinearLayer layers without an
intervening nonlinearity: *)
ContourPlot[
trainedClassifier[{x,y},None],
{x,-1,1},
{y,-1,1},
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
PlotLegends->Automatic,
LabelStyle->Directive[Black,10],
ImageSize->250,
PlotLabel->"Trained Classifier Decision Boundary"
]
(* Create a similar net with a Tanh nonlinearity between the two layers: *)
nonlinearClassifier=NetChain[
{
LinearLayer[20],ElementwiseLayer[Tanh],
LinearLayer[],ElementwiseLayer[LogisticSigmoid]
},
"Output"->NetDecoder["Boolean"]
]
220
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
{y,-1,1},
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
PlotLegends->Automatic,
LabelStyle->Directive[Black,10],
ImageSize->250,
PlotLabel->"Trained Nonlinear Classifier Decision Boundary"
]
Output
Output
Output
Output
221
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
Output
222
CHAPTER 4 MULTILAYER FEED-FORWARD NEURAL NETWORK
223
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
CHAPTER 5
CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Remark:
This chapter provides a Mathematica implementation of the concepts and ideas presented in Chapter 4, [1], of the
book titled Artificial Neural Network and Deep Learning: Fundamentals and Theory. We strongly recommend that
you begin with the theoretical chapter to build a solid foundation before exploring the corresponding practical
implementation.
Neural Networks (NNs) have revolutionized various fields, from image recognition to natural language processing,
by enabling machines to learn complex patterns and make decisions with human-like accuracy. However, despite their
remarkable capabilities, training NNs effectively remains a challenging task. This chapter delves into the myriad
challenges encountered during the optimization process of NNs, exploring key concepts such as activation function
(AF) saturation, vanishing and exploding gradients, weight initialization methods [47,48,49-53], non-zero centered
AFs [54], feature scaling techniques, including standardization, normalization, and whitening [55-61], and
normalization methods like Batch Normalization (BN) [62] and Layer Normalization (LN) [63].
• One of the fundamental challenges in NN optimization is AF saturation. AFs play a crucial role in
introducing non-linearity to the model, enabling it to learn complex patterns. However, certain AFs, such
as the Sigmoid or hyperbolic tangent (Tanh) functions, tend to saturate when the input values are too large
or too small, leading to vanishing gradients and hampering the learning process.
• The vanishing and exploding gradients problem is another significant hurdle faced during NN training. In
deep NNs, gradients can diminish exponentially or explode during backpropagation (BP), making it
challenging to update the weights effectively. This phenomenon hinders the convergence of the model and
affects its ability to generalize to unseen data.
• While non-zero centered AFs like ReLU and its variants indeed alleviate the vanishing gradient problem
(VGP), they can introduce another issue known as "zig-zag" updates. These updates occur when the
neuron's output oscillates between positive and negative values, causing the Gradient Descent (GD)
updates to zig-zag back and forth. This oscillatory behavior can potentially slow down the learning
process, as the network struggles to converge towards the optimal solution.
• Effective weight initialization is crucial for mitigating the issues of vanishing and exploding gradients.
Common weight initialization techniques, such as random initialization, aim to set initial weights to small
values to prevent saturation and maintain stable gradients during training. Kaiming or He initialization is
a popular weight initialization method designed specifically for deep NNs. It initializes the weights of
each layer based on the number of input units, effectively addressing the vanishing and exploding
gradients problem and promoting faster convergence. Xavier or Glorot initialization is another widely
used technique for weight initialization. It sets the initial weights using a uniform or normal distribution,
scaled based on the number of input and output units, thus ensuring stable gradients and facilitating
smoother training.
• Feature scaling techniques, including standardization, normalization, and whitening, are essential for
preprocessing input data and enhancing the convergence of NNs. These methods ensure that input features
are on similar scales, preventing certain features from dominating the learning process.
• BN and LN are techniques that normalize the activations of each layer, effectively stabilizing the learning
process and accelerating convergence. These techniques mitigate the effects of internal covariate shift and
facilitate smoother optimization of NNs.
224
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
In this chapter, building upon the foundational concepts established in earlier chapters, we delve deeper into the
realm of NN construction using Mathematica, exploring advanced functionalities and techniques to enhance the
efficiency and effectiveness of our models.
• Our first focus will be on monitoring training progress, a crucial aspect of NN development. We will discuss
methodologies and tools to track key performance metrics such as loss, accuracy, and convergence rates in
real-time. By closely monitoring training progress, developers can gain valuable insights into the behavior
of their models, enabling informed decisions and efficient optimization strategies.
• We will introduce NetPort and NetExtract, which serve as crucial components for managing the flow of
data within NN architectures. NetPort enables us to designate input and output ports within our networks,
facilitating the seamless integration of various data sources and outputs. NetExtract, on the other hand,
allows for the extraction of specific layers or parameters from networks, enabling the reusability and
customization of complex architectures.
• Next, we will discuss TrainingProgressMeasurements and TrainingProgressFunction, which provide
invaluable insights into the training process of NNs. These tools enable real-time monitoring and analysis of
key performance metrics, empowering developers to fine-tune models for optimal results efficiently.
• Furthermore, we will explore the NetTrainResultsObject, a comprehensive representation of the training
outcomes generated by the NetTrain function. This object encapsulates crucial information such as
training/validation losses, accuracies, and other performance metrics, facilitating in-depth analysis and
evaluation of model performance.
• Next, we address the challenge of saturation and vanishing gradients during training, which can hinder the
convergence of NNs, particularly in deep architectures. We explore techniques to mitigate these issues,
including advanced weight initialization methods. By effectively managing saturation and vanishing
gradients, developers can foster more stable and reliable training dynamics, leading to improved model
performance.
• In addition, we will delve into the initialization techniques, Xavier and Kaiming, using the NetInitialize
function. These techniques play a pivotal role in setting the initial weights of NN layers, influencing the
convergence and stability of the training process significantly.
• Furthermore, we will introduce the BatchNormalizationLayer, a fundamental tool for improving the
training efficiency and generalization of NNs. BN mitigates the issues of internal covariate shift, promoting
faster convergence and better performance across various tasks. The BatchNormalizationLayer can be
easily incorporated into NN architectures using the NetChain or NetGraph constructs. It can be placed after
a fully connected layer, or any other layer where normalization is desired.
• Finally, we delve into feature scaling techniques, specifically standardization, whitening, and Mahalanobis
distances. Feature scaling plays a critical role in ensuring the stability and convergence of NNs by
normalizing input data distributions. We examine the impact of different scaling methodologies on model
performance and explore best practices for incorporating them into the training pipeline.
Throughout this chapter, we will provide practical examples and demonstrations to illustrate the application of these
techniques. By mastering these advanced functionalities, readers will gain the necessary expertise to design, train, and
optimize sophisticated NNs using Mathematica, empowering them to tackle complex problems across diverse domains
effectively.
225
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Unit 5.1
NetPort and NetExtract
NetPort["port"]
represents the specified input or output port for a complete net.
NetPort[{n,"port"}]
represents the specified port for layer number n in a NetGraph or similar construct.
NetPort[{"name","port"}]
represents the specified port for the layer with the specified name.
NetPort[spec,port]
is treated as equivalent to NetPort[{spec,port}].
Remarks:
• NetPort[{layer, "port"}]: Refers to the named output port of a specific layer when used on the left-
hand side of a rule. When used on the right-hand side of a rule, it refers to a named input port of a layer.
• NetPort["port"]: Refers to an input of the entire graph when used on the left-hand side of a rule. When
used on the right-hand side of a rule, it refers to an output of the entire graph.
• net[data, NetPort[oport]] : Used to obtain the value of the net at a specific output port (oport) when
it's applied to the specified data. Here, oport must refer to an output port, a subnet of the net, or a layer.
• net[data, {NetPort[oport1], NetPort[oport2], …}]: Returns an association where the keys are the
specified output ports (oport1, oport2, etc.), and the values are the values of the net at those output ports
when the net is applied to the specified data.
net=NetInitialize@NetGraph[
{
LinearLayer[5,"Input"->2],ElementwiseLayer[Ramp],
LinearLayer[5],ElementwiseLayer[Tanh],
LinearLayer[5]
},
{1->NetPort["Output1"],3->NetPort["Output2"],1->2->3->4->5}
]
net[{-1.2,3.1},
{NetPort["Output1"],NetPort["Output2"],NetPort["Output"],NetPort[All,"Output"]}]
226
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output <|
Output1->{0.391137,6.67612,-7.2958,1.75662,-5.31164},
Output2->{-0.1352,-1.01155,-7.02377,0.932496,1.12231},
Output->{0.448372,-0.832601,0.217107,-0.230463,-0.525316},
NetPort[{1,Output}]->{0.391137,6.67612,-7.2958,1.75662,-5.31164},
NetPort[{2,Output}]->{0.391137,6.67612,0.,1.75662,0.},
NetPort[{3,Output}]->{-0.1352,-1.01155,-7.02377,0.932496,1.12231},
NetPort[{4,Output}]->{-0.134382,-0.766404,-0.999998,0.731756,0.80837},
NetPort[{5,Output}]->{0.448372,-0.832601,0.217107,-0.230463,-0.525316}
|>
net=NetInitialize@NetGraph[{TotalLayer[]},{NetPort["Input1"]-
>1,NetPort["Input2"]->1,NetPort["Input3"]->1}]
net[{4,5,5}]
Output
Output 14.
227
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Create a NetChain: *)
net=NetChain[{ElementwiseLayer[Tanh],ElementwiseLayer[Cos],ElementwiseLayer[Sin]}
]
(* Obtain the output of the first layer of the net when applied to data: *)
net[{-1.2,3.1},NetPort[1,"Output"]]
Output
Output {-0.833655,0.995949}
Output {-0.833655,0.995949}
Output <|
NetPort[{1,Output}]->{-0.833655,0.995949},
NetPort[{2,Output}]->{0.672174,0.543706}
|>
Output <|
NetPort[{1,Output}]->{-0.833655,0.995949},
NetPort[{2,Output}]->{0.672174,0.543706},
NetPort[{3,Output}]->{0.622689,0.517311}
|>
NetExtract[layer,"param"]
extracts the value of a parameter for the specified net layer.
NetExtract[net,lspec]
extracts the layer identified by lspec from within the NetGraph or NetChain object net.
NetExtract[net,{lspec,"param"}]
extracts the value of the parameter param from the layer identified by lspec in net.
Remarks:
• The layer specification can be an integer indicating the n^(th) layer or a string indicating a named layer.
• Parameter specifications can be the names of any of the arrays or options contained within a layer.
228
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Extract multiple layers (the first and third layers) from the neural network:
*)
NetExtract[chain,{{1},{3}}]
Output
229
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
Output
Output Tanh
Output
Output
230
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
and "linear2", connected sequentially where the output of "linear1" serves as the
input to "linear2". The subsequent operations involve extracting specific components
from the network. Firstly, it extracts the layer named "linear1", which retrieves
the first linear layer from the network. Secondly, it extracts all layers from the
network, providing a list containing both "linear1" and "linear2". These operations
exemplify the ability to access individual layers or all layers collectively within
a NetGraph object, facilitating tasks such as layer inspection and manipulation:
*)
Output
Output
Output
231
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output {{-0.359447,-0.0499231},{-1.12706,1.08654}}
Output
Output
232
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Unit 5.2
Monitor Training Progress
NetTrain[net,{input1->output1,input2->output2,…}]
trains the specified neural net by giving the inputi as input and minimizing the discrepancy between the outputi and
the actual output of the net, using an automatically chosen loss function.
Batch Size
Working
Learning Rate
Precision
Learning Rate
Validation Set
Multipliers
Training
Update Loss Function
Schedule
Training
Max Training
Stopping
Rounds
Criterion
NetTrain
Training Options
Progress Method
Reporting
Training
Performance
Progress
Goal
Function
Training
Progress Target Device
Measurements
Training
Progress
Time Goal
Check Random
pointing Seeding
TrainingProgressMeasurements and TrainingProgressFunction are options used to monitor and customize the
training process, while NetTrainResultsObject is the object containing information about the training results.
233
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
NetTrain[net,data,All]
gives a NetTrainResultsObject[…] that summarizes information about the training session.
NetTrainResultsObject[…]
represents an object generated by NetTrain that contains the trained net and other information about the training
process.
NetTrainResultsObject[…][prop]
is used to look up property prop from the NetTrainResultsObject.
234
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
NetTrain[net,data,TrainingProgressFunction->f]
TrainingProgressFunction
is an option for NetTrain that specifies a function to run periodically during training.
TrainingProgressFunction->f
specifies that f[assoc] is evaluated after every training round, where assoc is an association with the following keys:
235
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
NetTrain[net,data,"prop"]
gives data associated with a specific property prop of the training session.
Remarks:
• You can use any of the properties listed above as the third argument of NetTrain to retrieve specific
information about the training process and results.
236
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
• Using these properties, you can analyze the performance of your neural network during training, inspect the
trained model, and gather information that might be useful for further analysis or decision-making.
• An association of the form <|"Property"->prop,"Form"->form,"Interval"->int|> can be used to
specify a custom property whose value will be collected repeatedly during training.
• For a custom property, valid settings for prop can be any of the properties available in
TrainingProgressFunction, or a user-defined function that is given the association of all the properties.
Valid settings for form include "List", "TransposedList" and "Plot". Valid settings for "Interval" can
be "Batch", "Round" or a Quantity[…]. Supported units include "Batches", "Rounds", "Percent" and
time units like "Seconds", "Minutes" and "Hours".
NetTrain[net,data,TrainingProgressMeasurements->spec]
TrainingProgressMeasurements
is an option for NetTrain that specifies measurements to make while training is in progress.
For nets that contain a CrossEntropyLossLayer, the following built-in measurements are available:
"Accuracy" fraction of correctly classified examples
"Accuracy"->n fraction of examples with the correct result in the top n
"AreaUnderROCCurve" area under the ROC curve for each class
"CohenKappa" Cohen's kappa coefficient
"ConfusionMatrix" counts cij of class i examples classified as class j
"ConfusionMatrixPlot" plot of the confusion matrix
"Entropy" entropy measured in nats
"ErrorRate" fraction of incorrectly classified examples
"ErrorRate"->n fraction of examples with the incorrect result in the top n
"F1Score" F1 score for each class
"FScore"->β Fβ score for each class
"FalseDiscoveryRate" false discovery rate for each class
"FalseNegativeNumber" number of false negative examples
"FalseNegativeRate" false negative rate for each class
"FalseOmissionRate" false omission rate for each class
"FalsePositiveNumber" number of false positive examples
"FalsePositiveRate" false positive rate for each class
"Informedness" informedness for each class
"Markedness" markedness for each class
"MatthewsCorrelationCoefficient" Matthews correlation coefficient for each class
"NegativePredictiveValue" negative predictive value for each class
"Perplexity" exponential of the entropy
"Precision" precision for each class
"Recall" recall rate for each class
"ROCCurve" receiver operating characteristics (ROC) curve for each class
"ROCCurvePlot" plot of the ROC curve
"ScottPi" Scott's pi coefficient
"Specificity" specificity for each class
"TrueNegativeNumber" number of true negative examples
"TruePositiveNumber" number of true positive examples
237
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
For nets that contain a MeanSquaredLossLayer or MeanAbsoluteLossLayer, the following built-in measurements are
available:
"FractionVarianceUnexplained" the fraction of output variance left unexplained by the net
"IntersectionOverUnion" intersection over union for bounding boxes
"MeanDeviation" mean absolute value of the residuals
"MeanSquare" mean square of the residuals
"RSquared" coeficient of determination
"StandardDeviation" root mean square of the residuals
During the training process, NetTrain will compute these measurements at various intervals (e.g., after each training
batch or after each training epoch) and provide them as part of the training progress output. This information can help
you monitor the performance of your neural network as it learns from the data and make decisions about training
parameters or model architecture.
(* Define a neural network architecture with two hidden layers of 150 units each
and Tanh activation functions: *)
mlp=NetChain[{150,Tanh,150,Tanh,1}]
mlpTrainingResults["LossPlot"]
mlpTrainingResults["MeanBatchesPerSecond"]
mlpTrainingResults["OptimizationMethod"]
mlpTrainingResults["TrainedNet"]
mlpTrainingResults["TrainingNet"]
Output
238
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
Output 304.241
Output {ADAM,Beta1->0.9,Beta2->0.999,Epsilon->1/100000,GradientClipping-
>None,L2Regularization->None,LearningRate->Automatic,LearningRateSchedule-
>None,WeightClipping->None}
Output
Output
239
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Define a neural network architecture with two hidden layers of 150 units each
and Tanh activation functions: *)
mlp=NetChain[{150,Tanh,150,Tanh,1}]
Output
Output
240
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
241
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Replace the default progress panel with a dynamically updated plot of the current
behavior of the net: *)
242
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
Output
243
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Unit 5.3
Monitor Saturation and Vanishing Gradients During
Training
Manipulate[
(* Set random seed for reproducibility: *)
SeedRandom[randomSeed];
(* Generate Random Weight and Bias within specified boundaries: *)
weight=RandomReal[{minWeight,maxWeight}];
bias=RandomReal[{minBias,maxBias}];
(* Define Neural Network using NetChain: *)
neuralNet=NetChain[
{
LinearLayer[1,"Weights"->weight,"Biases"->bias],
(* Add activation function to the neural network: *)
ElementwiseLayer[activationFunction]
},
"Input"->1
];
(* Generate Random Input Data within specified boundaries: *)
inputData=RandomReal[{minInput,maxInput},{100,1}];
(* Apply Neural Network to Inputs: *)
outputData=neuralNet[inputData];
(* Plot Input Data and Outputs: *)
ListPlot[
Transpose[
{Flatten[inputData],Flatten[outputData]}],
PlotStyle->{PointSize[0.02],Purple},
PlotRange->All,
Frame->True,
FrameLabel->{"Input","Output"},
PlotLegends->Placed[{"Output"},{0.8,0.2}],
PlotLabel->"Activation Function Saturation with\n One-Dimensional Input",
ImageSize->250
],
(* Controls: *)
{{randomSeed,1,"Random Seed"},1,1000,1,Appearance->"Labeled"},
{{minWeight,-5,"Min Weight"},-10,0,0.1,Appearance->"Labeled"},
{{maxWeight,5,"Max Weight"},0,10,0.1,Appearance->"Labeled"},
{{minBias,-2,"Min Bias"},-5,0,0.1,Appearance->"Labeled"},
{{maxBias,2,"Max Bias"},0,5,0.1,Appearance->"Labeled"},
244
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
{{minInput,-10,"Min Input"},-20,0,1,Appearance->"Labeled"},
{{maxInput,10,"Max Input"},0,20,1,Appearance->"Labeled"},
{{activationFunction,LogisticSigmoid,"Activation Function"},
{LogisticSigmoid,Tanh},ControlType->PopupMenu}
]
Output
245
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
2,LogisticSigmoid,
(* Two neurons with logistic sigmoid activation for the second layer: *)
2,LogisticSigmoid,
(* Two neurons with logistic sigmoid activation for the third layer: *)
2,LogisticSigmoid,
(* One neuron with logistic sigmoid activation for the output layer: *)
1,LogisticSigmoid
},
{1->2->3->4->5->6->7->8},
(* Define input size: *)
"Input"->200
];
activationOutputLayer2=Values[trainingData][[2]];
activationOutputLayer4=Values[trainingData][[3]];
activationOutputLayer6=Values[trainingData][[4]];
activationOutputLayer8=Values[trainingData][[5]];
(* Calculate mean and standard deviation for each layer's activation outputs: *)
meanLayer2=Mean/@activationOutputLayer2;
stdDevLayer2=StandardDeviation/@activationOutputLayer2;
meanWithStdDevLayer2=Around@@@Transpose[{meanLayer2,stdDevLayer2}];
meanLayer4=Mean/@activationOutputLayer4;
stdDevLayer4=StandardDeviation/@activationOutputLayer4;
meanWithStdDevLayer4=Around@@@Transpose[{meanLayer4,stdDevLayer4}];
meanLayer6=Mean/@activationOutputLayer6;
stdDevLayer6=StandardDeviation/@activationOutputLayer6;
meanWithStdDevLayer6=Around@@@Transpose[{meanLayer6,stdDevLayer6}];
246
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
meanLayer8=Mean/@activationOutputLayer8;
(* Visualize mean activation values with error bars over training epochs: *)
ListLinePlot[
{meanWithStdDevLayer2,meanWithStdDevLayer4,meanWithStdDevLayer6,meanLayer8},
PlotStyle->{Opacity[0.6],Opacity[0.6],Opacity[0.6],Opacity[0.6]},
PlotRange->{0,1},
PlotLegends->{
"Mean of Activations Layer 2",
"Mean of Activations Layer 4",
"Mean of Activations Layer 6",
"Mean of Activations Layer 8"
},
IntervalMarkers->"Bars",
Frame->True,
FrameLabel->{"Epochs","Mean of Activation Values"},
PlotLabel->"Means with Standard Deviations (vertical bars)\n of the activation
values"
]
Output
Output
247
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
248
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
trainingData=Flatten@Table[{x,y}->{Exp[-Norm[{x,y}]]},{x,-3,3,.005},{y,-
3,3,.005}];
Output
249
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
250
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
origin. It achieves this by generating a dataset containing these pairs and defining
a neural network architecture with multiple layers and logistic sigmoid activation
functions. The network is then initialized with random weights and biases before
being trained on the dataset. During training, the evolution of the root mean square
(RMS) values of the weights for each layer is monitored to visualize the training
progress and diagnose potential issues such as vanishing gradients. The training
process is limited to 10 rounds with a batch size of 1024.
Monitoring the RMS values of the weights for each layer of the neural network
provides insights into how the weights are being adjusted during training. If the
RMS values of the weights do not change significantly over time (i.e., they remain
relatively constant or change only minimally), it suggests that the gradients in
those layers are small. This indicates that the network is experiencing difficulty
in learning meaningful representations or updating the parameters effectively in
those layers. Small changes in the RMS values of the weights imply that the gradients
are not providing sufficiently strong signals to guide meaningful updates to the
weights. This situation often indicates the presence of vanishing gradients: *)
251
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
252
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
<|
(* Monitor gradients: *)
"Property"->"Gradients",
(* Monitor gradients over rounds: *)
"Interval"->"Rounds"
|>,
MaxTrainingRounds->10,
BatchSize->1024
];
253
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
BoxRatios->{1,1,1},
PlotRange->All,
ImageSize->250,
AxesLabel->{"Epoch","Gradient Value","Density"},
PlotLabel->"Densities of the Last Layer Gradients"
]
(* Plot the gradient distribution with respect to weights of the first layer for
10 epochs: *)
firstLayerWeightsGradientData=Table[
Flatten[
Table[
Values[gradients][[i]][[2]],
{i,1,10}][[j]]
],
{j,1,10}]//Normal;
DistributionChart[
firstLayerWeightsGradientData,
Joined->"Mean",
ChartElementFunction->"PointDensity",
ChartStyle->"Pastel",
ImageSize->300,
FrameLabel->{"Epochs of First Layer","Gradient Values"},
PlotLabel->"Gradient Distribution with Respect \n to Weights of the First Layer
for 10 Epochs"
]
(* Plot the gradient distribution with respect to weights of the last layer for 10
epochs: *)
firstLayerWeightsGradientData=Table[
Flatten[
Table[
Values[gradients][[i]][[8]],
{i,1,10}][[j]]
],
{j,1,10}]//Normal;
DistributionChart[
firstLayerWeightsGradientData,
Joined->"Mean",
ChartElementFunction->"PointDensity",
ChartStyle->"Pastel",
ImageSize->300,
FrameLabel->{"Epochs of Last Layer","Gradient Values"},
PlotLabel->"Gradient Distribution with Respect \n to Weights of the Last Layer
for 10 Epochs"
]
(* Plot the gradient distribution with respect to weights of the 4 layers in the
first epoch: *)
firstEpochLayerWeightsGradientData=Table[
Flatten[
Table[
Values[gradients][[1]][[i]],
{i,2,8,2}
][[j]]
],
{j,1,4}
]// Normal;
254
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
DistributionChart[
firstEpochLayerWeightsGradientData,
Joined->"Mean",
ChartElementFunction->"PointDensity",
ChartStyle->"Pastel",
ImageSize->300,
FrameLabel->{"Layers","Gradient Values"},
PlotLabel->"Gradient Distribution with Respect \n to Weights of the 4 Layers in
the First Epoch"
]
(* Histogram of the Gradient with Respect to Weights of the Fisrt and Last Layers
for 10 Epocks: *)
Table[
Table[
Histogram[
data=Flatten[
Table[
Values[gradients][[i]][[k[[2]]]],
{i,1,10}
][[j]]
]// Normal,
Automatic,
Epilog->{
Blue,
PointSize[0.03],
Point[{
{StandardDeviation[data],0},
{Mean[data],0},
{-StandardDeviation[data],0}
}]
},
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->200,
PlotRange->Full,
PlotLabel->Style[Row[{"Gradients of ",k[[1]],": Epock ",j}]]
],
{j,1,10}
],
{k,{{"First Layer",2},{"Last Layer",8}}}
]
Output
255
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
Output
Output
256
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
257
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Unit 5.4
NetInitialize (Xavier and Kaiming)
xavierInitialize[nIn_,nOut_]:=Module[
{scale},
scale=Sqrt[6/(nIn+nOut)];
RandomVariate[UniformDistribution[{-scale,scale}],{nOut,nIn}]
]
(*Example usage*)
nIn=20; (*Number of input neurons*)
nOut=30; (*Number of output neurons*)
weights=xavierInitialize[nIn,nOut];
(* Plot the weight distributions with respect to weights of layer with nIn=20 and
nOut=30: *)
DistributionChart[
weights,
258
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Joined->"Mean",
ChartElementFunction->"PointDensity",
ChartStyle->"Pastel",
ImageSize->300,
FrameLabel->{"Neurons","Weights"},
PlotLabel->"Weight Distributions using Xavier initialized Weights \n of the 30
Neurons"
]
Output
Output
259
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
(*Example usage*)
nIn=20; (*Number of input neurons*)
nOut=30; (*Number of output neurons*)
weights=xavierInitialize[nIn,nOut];
260
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Plot the weight distributions with respect to weights of layer with nIn=20 and
nOut=30: *)
DistributionChart[
weights,
Joined->"Mean",
ChartElementFunction->"PointDensity",
ChartStyle->"Pastel",
ImageSize->300,
FrameLabel->{"Neurons","Weights"},
PlotLabel->"Weight Distributions using Xavier initialized Weights \n of the 30
Neurons"
]
261
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
Output
kaimingInitialize[nIn_,nOut_,distribution_:NormalDistribution[0,1]]:=Module[
{scale},
scale=Sqrt[2/nIn];
RandomVariate[distribution,{nOut,nIn}]*scale
262
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
];
(*Example usage*)
nIn=20; (*Number of input neurons*)
nOut=30; (*Number of output neurons*)
weights=kaimingInitialize[nIn,nOut];
(* Plot the weight distributions with respect to weights of layer with nIn=20 and
nOut=30: *)
DistributionChart[
weights,
Joined->"Mean",
ChartElementFunction->"PointDensity",
ChartStyle->"Pastel",
ImageSize->300,
FrameLabel->{"Neurons","Weights"},
PlotLabel->"Weight Distributions using Kaiming Initialized Weights \n of the 30
Neurons"
]
263
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
Output
264
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Histogram[
Flatten[weightsFirstLayerUniform],
20,
PlotRange->All,
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->250,
Frame->True,
FrameLabel->{"Weight","Frequency"},
PlotLabel->"Xavier Initialized Weights Histogram \n (Uniform Distribution)"
]
weightsFirstLayerNormal=NetExtract[initializedNetworkNormal,{1,"Weights"}];
265
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
FrameLabel->{"Weight","Frequency"},
PlotLabel->"Xavier Initialized Weights Histogram \n (Normal Distribution)"
]
Output
Output
266
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Flatten[weightsFirstLayerbefore],
20,
PlotRange->All,
ColorFunction->Function[{height},Opacity[height]],
ChartStyle->Purple,
ImageSize->250,
Frame->True,
FrameLabel->{"Weight","Frequency"},
PlotLabel->"Xavier Initialized Weights Histogram \n before training (Uniform
Distribution)"
]
(* Train the initialized network and monitor training progress using weights
property: *)
weights=NetTrain[
netInitialize,
data,
(* Monitor training progress using Weights property: *)
<|
"Property"->"Weights",
"Interval"->"Rounds"
|>,
MaxTrainingRounds->10
];
267
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Joined->True,
BoxRatios->{1,1,1},
PlotRange->All,
ImageSize->250,
AxesLabel->{"Epoch","Weights","Density"},
PlotLabel->"Densities of the First Layer Weights \n for 10 Epochs"
]
Output
Output
Output
Output
268
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Unit 5.5
Feature Scaling: Standardize, Whitenend and
Mahalanobis Distances
Standardize[list]
shifts and rescales the elements of list to have zero mean and unit sample variance.
Standardize[list,f1]
shifts the elements in list by f1[list] and rescales them to have unit sample variance.
Standardize[list,f1,f2]
shifts by f1[list] and scales by f2[list].
Remarks:
• Standardize shifts by a location and rescales by a scale estimated from the elements of list.
• Standardize[list] is effectively (list-Mean[list])/StandardDeviation[list] for nonzero
StandardDeviation[list].
• Standardize[list,f1] is effectively (list-f1[list])/StandardDeviation[list].
• Standardize[list,f1,f2] is effectively (list-f1[list])/f2[list].
Output {0.75705,-1.99453,0.85896,-0.0582346,0.247497,0.655139,-0.465877}
Output {0.,1.}
269
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output {
(2 a - b - c)/( Sqrt[3] Sqrt[a^2 + b^2 - b c + c^2 - a (b + c)]),
-((a - 2 b + c)/( Sqrt[3] Sqrt[a^2 + b^2 - b c + c^2 - a (b + c)])),
-((a + b - 2 c)/( Sqrt[3] Sqrt[a^2 + b^2 - b c + c^2 - a (b + c)]))
}
sampledData=RandomReal[NormalDistribution[4,1],200];
(* Standardize data: *)
standardizedData=Standardize[sampledData];
(* Calculate standard deviation of standardized data: *)
standardDeviationStandardized=StandardDeviation[standardizedData];
(* Calculate mean of standardized data: *)
meanValueStandardized=N[Mean[standardizedData]];
(* Get length of standardized data: *)
dataLengthStandardized=Length[standardizedData];
(* Plotting the original data with mean and standard deviation bands: *)
ListPlot[
{
sampledData,
{{0,meanValue},{dataLength,meanValue}},
{{0,meanValue-standardDeviation},{dataLength,meanValue-standardDeviation}},
{{0,meanValue+standardDeviation},{dataLength,meanValue+standardDeviation}}
},
Joined->{False,True,True,True},
Filling->{1->meanValue,3->{4}},
PlotStyle->{Purple,Automatic,Automatic,Automatic},
270
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Plotting the standardized data with mean and standard deviation bands: *)
ListPlot[
{
standardizedData,
{
{0,meanValueStandardized},
{dataLengthStandardized,meanValueStandardized}
},
{
{0,meanValueStandardized-standardDeviationStandardized},
{dataLengthStandardized,meanValueStandardized-standardDeviationStandardized}
},
{
{0,meanValueStandardized+standardDeviationStandardized},
{dataLengthStandardized,meanValueStandardized+standardDeviationStandardized}
}
},
Joined->{False,True,True,True},
Filling->{1->meanValueStandardized,3->{4}},
PlotStyle->{Purple,Automatic,Automatic,Automatic},
PlotLegends->{"SData","Mean","Lower standard deviation band","Upper standard
deviation band"},
AxesLabel->Automatic,
ImageSize->250
]
Output
Output
271
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Plotting: *)
GraphicsRow[
{
ListPlot[
originalData,
PlotStyle->{PointSize[0.02],Opacity[0.4],Blue},
PlotLabel->"Original Correlated Data",
ImageSize->250
],
ListPlot[
decorrelatedData,
Epilog->{PointSize[0.02],Green,Point[covDecorrelated]},
PlotStyle->{PointSize[0.02],Opacity[0.4],Red},
PlotLabel->"Decorrelated Data",
ImageSize->250
],
ListPlot[
whitenedData,
Epilog->{PointSize[0.02],Green,Point[covWhitened]},
AspectRatio->1,
PlotStyle->{PointSize[0.02],Opacity[0.4],Purple},
PlotLabel->"Whitened Data",
ImageSize->250
]
}
]
272
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Explanation: *)
Print["Eigenvalues: ",eigenvalues];
Print["Eigenvectors: ",eigenvectors];
Print["Covariance Matrix of Original Correlated Data: ",covarianceMatrix];
Print["Covariance Matrix of Decorrelated Data: ",covDecorrelated];
Print["Covariance Matrix of Whitened Data: ",covWhitened];
Output
Output Eigenvectors:
{
{-0.822513,-0.568747},
{0.568747,-0.822513}
}
SeedRandom[23];
(* Generate data from a bivariate normal distribution: *)
sampleData=RandomVariate[BinormalDistribution[{0,0},{1,3},0.9],200];
273
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Transpose[eigenSystem[[2]]].DiagonalMatrix[Sqrt[eigenSystem[[1]]]].eigenSystem[[2]
]
(* eigenSystem[[1]] contains eigenvalues, eigenSystem[[2]] contains eigenvectors:
*)
]
274
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
275
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
276
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Unit 5.6
BatchNormalizationLayer
MovingAverage[list,r]
gives the moving average of list, computed by averaging runs of r elements.
MovingAverage[list,{w1,w2,…,wr}]
gives the moving average of list, computed with weights wi.
ExponentialMovingAverage[list,α]
gives the exponential moving average of list with smoothing constant α.
MovingMedian[list,r]
gives the moving median of list, computed using spans of r elements.
MovingMap[f,data,w]
applies f to size w windows in the specified data.
MovingMap[f,data,wspec]
uses windows specified by wspec.
Remarks:
• MovingAverage[list,r] gives a list of the means of elements in list taken in blocks of length r.
• MovingAverage gives a list of length Length[list]-r+1.
• The smoothing constant α is typically a number between 0 and 1, but can be any expression.
• ExponentialMovingAverage[x,α] generates a list of results in which .
• The output from ExponentialMovingAverage[list,α] has the same length as list.
• MovingMedian gives a list of the medians of elements in list taken in blocks of length r.
• MovingMedian gives a list of length Length[list]-r+1.
Output {(a+b)/2,(b+c)/2,(c+d)/2,(d+e)/2}
Output {1/3 (a+2 b),1/3 (b+2 c),1/3 (c+2 d),1/3 (d+2 e)}
Output {13/3,5,16/3,11/3}
Output {3.26667,4.36667,3.4,3.76667}
277
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* The goal of this code is to generate a dataset with noisy fluctuations, then
smooth out these fluctuations using a moving average filter, and finally visualize
both the original noisy data and the smoothed data: *)
Output
(* Plotting: *)
ListLinePlot[
plotData,
PlotRange->{0.8,1.2},(*Set the range of the y-axis: *)
PlotLegends->{"Original Data","MA(10)","MA(20)","MA(30)","MA(40)"},
ImageSize->300
]
278
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
279
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Average for different smoothing constants (0.1, 0.3 and 0.6) to smooth out the data
and highlight underlying trends. Finally, it plots the original data alongside the
Exponential Moving Average, offering a visual representation of the trend and the
effectiveness of different smoothing constants in capturing the underlying patterns:
*)
(* Prepend original data to the list of Exponential Moving Average for plotting:
*)
plotData=Prepend[exponentialMovingAverage,initialData[[1;;550]]];
(* Plotting: *)
ListLinePlot[
plotData,
PlotRange->{0.8,1.2},(*Set the range of the y-axis*)
PlotLegends->{"Original Data","EMA(0.6)","EMA(0.3)","EMA(0.1)"},
ImageSize->300
]
Output
Output {a,a,a,a}
Output {a,b,c,d}
280
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Manipulate[
(* Set seed for reproducibility: *)
SeedRandom[seed];
(* Generate synthetic data with random noise: *)
initialData=ConstantArray[1.,numSamples]+RandomReal[{-0.1,0.1},numSamples];
Output
Output {2,5,5,4,3}
281
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output {-9,5,10,-7,6,2,1,7,3,-10}
Output {5,5,6,2,2,2,3,3}
Output {5,5,6,2,2,2,3,3}
Output {-8, -1, 3, 6, -1, 3, 4, 1, -3, 5, -6, 4, 9, -1, -4, 1, -2, 10, -1, -8, 0, 0, -3,
-1, 10, 9, 5, 0, -8, -4, 4, -8, -5, -10, -8, -3, -10, -7, 6, -4}
282
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output {181/10, 1309/90, 662/45, 908/45, 115/6, 326/15, 64/3, 314/15, 907/30, 517/18,
1598/45, 1388/45, 148/5, 316/15, 316/15, 1382/45, 1702/45, 1123/30, 2689/90,
1712/45, 1448/45, 496/15, 208/5, 1958/45, 4861/90, 785/18, 2461/90, 938/45,
1589/90, 553/18, 553/18}
BatchNormalizationLayer[]
represents a trainable net layer that normalizes its input data by learning the data mean and variance.
Remarks:
• With Automatic settings, the biases, scaling, moving mean and moving variance arrays are initialized
automatically when NetInitialize or NetTrain is used.
• If biases, scaling, moving variance and moving mean have been set, BatchNormalizationLayer[…][input]
explicitly computes the output from applying the layer.
• BatchNormalizationLayer[…][{input1,input2,…}] explicitly computes outputs for each of the inputi.
Output
283
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output {0.,0.,0.}
Output {1.,1.,1.}
Output {0.,0.,0.}
Output {1.,1.,1.}
Output 0.001
Output 0.9
Output {1.999,2.9985,3.998}
284
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output {1.,-1.30993,2.38013}
(* Applying the layer to any input returns the value for the "Biases" parameter:*)
batchnorm[{1,2,3}]
batchnorm[{3,4,5}]
Output
Output {1.,2.,20.}
Output {1.,2.,20.}
285
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
moving means, and variances. Conversely, the built-in function streamlines the
process by initializing a batch normalization layer with predefined parameters,
offering a more concise and efficient solution. By manually computing batch
normalization, we gain a deeper understanding of its inner workings. However, it's
important to note that in practice, deep learning frameworks like Mathematica provide
efficient built-in implementations that handle the computation automatically,
allowing for easier experimentation and faster training: *)
(*Example usage*)
scalings=0.5;
biases=0.1;
movingMeans=0.2;
movingVariances=0.3;
epsilon=10^-5;
input=0.3;
normalizedOutput=batchNormalizationLayer[input, scalings, biases, movingMeans,
movingVariances, epsilon]
batchnorm=NetInitialize@BatchNormalizationLayer[
"Scaling"->0.5,
"Biases"->0.1,
"Epsilon"->10^-5,
"MovingMean"->0.2,
"MovingVariance"->0.3,
"Input"->1
];
batchnorm[0.3]
Output 0.191286
Output {0.191286}
Manipulate[
Module[
{data,normalizedData,batchnorm},
(* Set the random seed: *)
SeedRandom[seed];
(* Generate a random dataset: *)
data=RandomReal[{-10,10},{numberOfSamples,1}];
(* Initialize the BatchNormalizationLayer with custom parameters: *)
batchnorm=NetInitialize@BatchNormalizationLayer[
"Scaling"->scaling,
286
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
"Biases"->biases,
"Epsilon"->epsilon,
"Momentum"->momentum,
"MovingMean"->movingMean,
"MovingVariance"->movingVariance,
"Input"->1
];
(* Apply the BatchNormalizationLayer to the dataset: *)
normalizedData=Flatten[batchnorm/@data];
Output
287
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Normalization layers into the MLP architecture, trains the modified network, and
evaluates its performance. The Batch-Normalized MLP demonstrates better
generalization, providing a smoother fit to the original Gaussian curve and
mitigating the overfitting observed in the initial MLP: *)
(* Define a neural network architecture with two hidden layers of 150 units each
and Tanh activation functions: *)
mlp=NetChain[{150,Tanh,150,Tanh,1}]
(* The resulting neural network overfits the data, capturing both the underlying
function and the noise. To visualize this, plot the function learned by the network
alongside the original data: *)
(* Plot the function learned by the trained neural network alongside the original
noisy dataset: *)
Show[
Plot[
overfittedMLP[x],
{x,-3,3},
PlotLabel->"Overfitted MLP",
ImageSize->250
],
noisyPlot
]
(* Define a neural network architecture with Batch Normalization layers after each
hidden layer: *)
batchNormMLP=NetChain[
{
150,BatchNormalizationLayer[],Tanh,
150,BatchNormalizationLayer[],Tanh,
1
}
]
288
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Extract the trained Batch-Normalized neural network from the training results:
*)
batchNormTrainedNet=batchNormTrainingResults["TrainedNet"];
Output
Output
289
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
Output
Output
Output
290
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
and biases, and proceeds to train it using the generated data while monitoring
activation output statistics. The code extracts and processes activation output data,
calculating mean and standard deviation values for both BatchNormalization and
LogisticSigmoid layers. Visualization steps include plotting mean activation values
with error bars over training epochs, performing kernel density estimation and
visualization, and creating histograms to depict the distribution of activation
values for specific layers. BatchNormalization normalizes the inputs to each layer,
helping to prevent activations from becoming too large or too small, which can lead
to saturation. By normalizing the inputs, BatchNormalization helps to keep the
activations within a more stable range, thereby alleviating the saturation problem
associated with the logistic sigmoid function. The figures generated by the code
illustrate various aspects of the neural network training process and activation
behaviors. The first set of figures depicts the mean activation values with error
bars over training epochs for both BatchNormalization and LogisticSigmoid layers,
showcasing their convergence patterns and variability. Additionally, kernel density
estimation plots visualize the distribution of activation values for specific layers,
demonstrating the spread and density of activations throughout training. Histograms
further elucidate the distribution of activation values for specific LogisticSigmoid
layers, offering insights into the diversity and concentration of activations: *)
291
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Function to process activation output data and calculate mean and standard
deviation: *)
processLayer[output_]:=Module[
{mean,stdDev,meanWithStdDev},
mean=Mean/@output;
stdDev=StandardDeviation/@output;
meanWithStdDev=Around@@@Transpose[{mean,stdDev}];
meanWithStdDev
]
(* Calculate mean and standard deviation for each BN layer's activation outputs: *)
{
meanWithStdDevBNLayer2,
meanWithStdDevBNLayer5,
meanWithStdDevBNLayer8
}=processLayer/@{
BNactivationOutputLayer2,
BNactivationOutputLayer5,
BNactivationOutputLayer8};
(* Calculate mean and standard deviation for each LogisticSigmoid layer's activation
outputs: *)
{
meanWithStdDevLogisticLayer3,
meanWithStdDevLogisticLayer6,
meanWithStdDevLogisticLayer9
}=processLayer/@{
LogisticactivationOutputLayer3,
LogisticactivationOutputLayer6,
LogisticactivationOutputLayer9};
(* Visualize mean BN activation values with error bars over training epochs: *)
ListLinePlot[
{
meanWithStdDevBNLayer2,
meanWithStdDevBNLayer5,
meanWithStdDevBNLayer8
},
PlotStyle->{Opacity[0.6],Opacity[0.6],Opacity[0.6]},
PlotRange->Full,
PlotLegends->{
292
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
(* Visualize mean Logistic activation values with error bars over training epochs:
*)
ListLinePlot[
{
meanWithStdDevLogisticLayer3,
meanWithStdDevLogisticLayer6,
meanWithStdDevLogisticLayer9
},
PlotStyle->{Opacity[0.6],Opacity[0.6],Opacity[0.6]},
PlotRange->Full,
PlotLegends->{
"Mean of Logistic layer 3",
"Mean of Logistic layer 6",
"Mean of Logistic layer 9"
},
IntervalMarkers->"Bars",
Frame->True,
FrameLabel->{"Epochs","Mean of Logistic Activation Values"},
PlotLabel->"Means with Standard Deviations (vertical bars)\n of the Logistic
activation values"
]
{
SKBNactivationLayer2,SKBNactivationLayer5,
SKBNactivationLayer8,SKLogisticactivationLayer3,
SKLogisticactivationLayer6,SKLogisticactivationLayer9
}=createSmoothKernels/@{
BNactivationOutputLayer2,BNactivationOutputLayer5,
BNactivationOutputLayer8,LogisticactivationOutputLayer3,
LogisticactivationOutputLayer6,LogisticactivationOutputLayer9};
293
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
PlotRange->All,
ImageSize->300,
AxesLabel->{"Epocks","Activation values","Density"},
PlotLabel->Style[Row[{"Distributions of Logistic Layer ",layer[[1]]}]]
]
,{layer,{
{"3",SKLogisticactivationLayer3},
{"6",SKLogisticactivationLayer6},
{"9",SKLogisticactivationLayer9}
}
}
]
Output
294
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
295
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
Output
296
CHAPTER 5 CHALLENGES IN NEURAL NETWORK OPTIMIZATION
297
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
CHAPTER 6
LEARING RATE SCHEDULES AND GRADIENT DESCENT
VARIANTS
Remark:
This chapter provides a Mathematica implementation of the concepts and ideas presented in Chapter 5, [1], of the
book titled Artificial Neural Network and Deep Learning: Fundamentals and Theory. We strongly recommend that
you begin with the theoretical chapter to build a solid foundation before exploring the corresponding practical
implementation.
In deep learning, the optimization process lies at the heart of training Neural Networks (NNs). Central to this
optimization is the notion of the learning rate, a crucial hyperparameter that dictates the step size in the parameter
space during optimization. Selecting an appropriate learning rate and its schedule significantly impacts the
convergence speed and the final performance of the model. In this chapter, we delve into various learning rate
schedules and adaptive algorithms that play pivotal roles in optimizing NNs. By understanding these techniques,
practitioners can fine-tune their training processes and achieve better results in their machine-learning endeavors.
The chapter initiates an exploration of learning rate schedules [64-75], which entail predefined strategies for
altering the learning rate throughout the training process. Learning rate schedules include step decay, inverse time
decay, exponential decay, polynomial decay with warm restart, cyclical learning rate, stochastic gradient descent with
warm restarts (cosine decay), exponential decay sine wave learning rate, Hessian-aware learning rate decay, etc., each
with its own advantages and drawbacks. Understanding and appropriately implementing these schedules are crucial
for achieving optimal convergence without encountering issues such as slow convergence or overshooting the minima.
Transitioning from learning rate schedules, we explore accelerated gradient descent [76-79], a variant of the
traditional GD algorithm designed to speed up convergence. Two popular accelerated gradient descent algorithms are
SGD with momentum and Nesterov accelerated gradient descent. In both cases, the momentum term helps the
optimization algorithm to continue moving in the same direction or accelerate in the relevant direction, even if the
gradient changes direction frequently or the surface of the loss function is highly irregular. Both methods help in
smoothing out the updates, which is particularly useful when dealing with noisy or high-variance gradients common
in SGD. The momentum term helps navigate through the irregularities of the loss surface more effectively, leading to
a smoother and often faster path to the minimum. By leveraging past gradients, these methods can speed up
convergence, reducing the time and computational resources needed for training. This leads to faster convergence and
better overall performance in training NNs and other machine-learning models.
Following the discussion on accelerated gradient descent, we turn our attention to adaptive learning rate algorithms
[80-93]. Adaptive learning rate algorithms adaptively adjust the learning rate during training based on past gradients,
and other relevant metrics. These algorithms aim to strike a balance between the benefits of using large learning rates
for fast convergence and the stability provided by smaller learning rates to prevent overshooting or oscillations.
Popular examples include AdaGrad, RMSProp, AdaDelta, Adam, AdaMax, Nadam, and AMSGRAD, each with its
own approach to adaptively scale the learning rates for individual model parameters.
Moreover, we explore second-order optimization methods [11,15,25,37]. Second-order optimization methods, such
as Newton, Marquardt, and variants like conjugate gradient (Hestenes-Stiefel formula, Polak-Ribiere formula,
Fletcher-Reeves formula), and quasi-Newton (rank one correction, DFP, and BFGS), etc., leverage information from
the second derivatives of the loss function to guide the optimization process. By incorporating curvature information,
these methods can converge faster and more accurately than first-order methods like GD. However, they often come
298
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
with higher computational costs and memory requirements due to the need to compute and store second-order
derivatives or their approximations.
This chapter serves as a continuation of the foundational principles introduced in Chapter 5. Here, we delve into
the intricate landscape of learning rate schedules and adaptive algorithms, employing the computational power of
Mathematica to elucidate their mechanisms and applications. Divided into two units, this chapter demystifies these
fundamental concepts.
The first unit serves as a foundational exploration of learning rate schedules and adaptive optimization algorithms,
leveraging the dynamic capabilities of Mathematica to provide intuitive insights. By building optimization algorithms
from scratch, the reader gains a deeper understanding of the underlying principles. Through interactive manipulations,
readers are guided step by step to comprehend the nuances of various algorithms. From elucidating traditional learning
rate schedules such as step decay, inverse time decay, and exponential decay to unraveling sophisticated techniques
like accelerated gradient descent and adaptive learning rate algorithms, this unit equips readers with a profound
understanding of the mechanisms driving optimization processes. Moreover, Mathematica provides a comprehensive
suite of built-in functions and tools for optimization, enabling users to implement, analyze, and visualize a diverse
range of optimization problems.
In the second unit, the focus shifts towards practical applications, centering on the optimization of NNs using
learning rate schedules and adaptive algorithms within the Mathematica environment. In this unit, we explore the
powerful capabilities of Mathematica's NetTrain function, leveraging a range of optimization methods and
suboptions to fine-tune the training process and enhance model performance. NetTrain serves as the cornerstone of
NN training within Mathematica, providing a versatile and user-friendly interface for optimizing model parameters.
At the heart of NetTrain lies a suite of optimization methods, including "ADAM", "RMSProp", "SGD", and "SignSGD",
each offering unique strategies for navigating the high-dimensional parameter space of NNs. We will not only explore
the selection and utilization of these optimization methods but also, we will go into the intricacies of their associated
suboptions. These suboptions, including "Momentum", "Beta1", "Beta2", and "Epsilon", provide users with fine-
grained control over the optimization process, allowing for nuanced adjustments to suit the specific requirements of
their NN architectures and training objectives.
Furthermore, the "LearningRateSchedule" suboption allows you to specify a learning rate schedule, which can
be a fixed learning rate, a schedule that decreases the learning rate over time (such as exponential decay or step decay),
or any other custom schedule you define. Through comprehensive demonstrations and hands-on exercises, this unit
empowers practitioners to harness the full potential of learning rate schedules and adaptive algorithms in enhancing
the performance of NNs.
Together, these units shed light on the nuanced interconnections among learning rate schedules, adaptive
algorithms, and NN optimization.
299
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Unit 6.1
Understanding Learning Rate Schedules and Adaptive
Algorithms with Mathematica
Mathematica Code 6.1 Step Decay
Input (* The code implements an interactive visualization tool using Mathematica's
Manipulate function to explore the behavior of a step decay learning rate schedule.
Users can adjust two parameters, the drop factor (d) and step size (s), via sliders
to observe their impact on the learning rate decay. The code defines a step decay
function that computes the learning rate based on the initial learning rate, drop
factor, step size, and current iteration. Data points representing the learning
rate at each iteration are generated and plotted dynamically: *)
Manipulate[
Module[
{data},
(* Define step decay function: *)
stepDecay[initialLearningRate_,dropFactor_,stepSize_,currentIteration_]:=initialL
earningRate*dropFactor^Floor[currentIteration/stepSize];
(*Generate data for the selected dropFactor value (d) and step size (s)*)
data=Table[{i,stepDecay[initialLearningRate,d,s,i]},{i,0,100}];
300
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Manipulate[
Module[
{data},
(* Define inverse time decay function: *)
inverseTimeDecay[initialLearningRate_,decayRate_,currentIteration_]:=initialLearn
ingRate/(1+decayRate*currentIteration);
301
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Manipulate[
Module[
{data},
(* Define standard exponential decay function: *)
exponentialDecay[initialLearningRate_,decayRate_,currentIteration_]:=initialLearn
ingRate*Exp[-decayRate*currentIteration];
(* Generate data for the learning rate with the selected parameters: *)
data=Table[{i,exponentialDecay[initialLearningRate,decayRate,i]},{i,0,100}];
Output
Manipulate[
Module[
{dataExp,dataInvTime},
302
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
exponentialDecay[initialLearningRate_,decayRate_,currentStep_]:=initialLearningRate
*Exp[-decayRate*currentStep];
inverseTimeDecay[initialLearningRate_,decayRate_,currentIteration_]:=initialLearnin
gRate/(1+decayRate*currentIteration);
dataInvTime=Table[{i,inverseTimeDecay[initialLearningRate,decayRate,i]},{i,0,100}];
(* Manipulate parameters: *)
{{initialLearningRate,0.7,"Initial Learning Rate"},0.01,1,0.01},
{{decayRate,0.1,"Decay Rate"},0.01,0.9,0.001}
]
Output
303
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
the learning rate over iterations are generated and plotted using ListLinePlot,
with the plot displaying the decay curve: *)
Manipulate[
Module[
{data},
(* Define polynomial decay function: *)
polynomialDecay[initialLearningRate_,power_,totalIterations_,currentIteration_]:
=initialLearningRate*(1-currentIteration/totalIterations)^power;
data=Table[{i,polynomialDecay[initialLearningRate,power,totalIterations,i]},{i,0
,totalIterations}];
Output
304
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Piecewise[
{
{{currentLearningRate,totalEpoch}={initialLearningRate,restartPoints[[1]]};,
restartPoints[[1]]>=currentIterations>=1},
{{currentLearningRate,totalEpoch}={initialLearningRate*0.65,restartPoints[[2]]};,
restartPoints[[2]]>=currentIterations>=restartPoints[[1]]+1},
{{currentLearningRate,totalEpoch}={initialLearningRate*0.65^2,restartPoints[[3]]};
,
restartPoints[[3]]>=currentIterations>=restartPoints[[2]]+1},
{{currentLearningRate,totalEpoch}={initialLearningRate*0.65^3,totalEpochs};,
totalEpochs>=currentIterations>=restartPoints[[3]]+1}
}
];
currentLearningRate*(1-currentIterations/totalEpoch)^power
];
(* Parameters: *)
initialLearningRate=0.2;
powers={0.9,0.7,0.5};
totalIterations=1000;
restartFractions={0.25,0.5,0.75};
{i,polynomialDecayWithRestart[initialLearningRate,power,totalIterations,restartFra
ctions,i]},
{i,0,totalIterations}
],
{power,powers}
];
305
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Output
cycle=Floor[1+epoch/(2*stepsize)];
x=Abs[epoch/stepsize-2*cycle+1];
Manipulate[
Module[
{epochs,learningRates},
(* Calculate learning rates for each epoch using the triangularLR function: *)
learningRates=triangularLR[#,stepsize,baseLR,maxLR]&/@epochs;
306
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Joined->True,
Mesh->All,
MeshStyle->Directive[PointSize[0.01],Purple],
ImageSize->300
]
],
(* Manipulate parameters: *)
{{baseLR,0.1,"Base Learning Rate"},0.1,0.2,0.0001,Appearance->"Labeled"},
{{maxLR,0.2,"Max Learning Rate"},0.2,0.3,0.001,Appearance->"Labeled"},
{{stepsize,5,"Half Cycle Length"},5,10,1,Appearance->"Labeled"},
{{totaliterations,100,"Total Epochs"},10,200,20,Appearance->"Labeled"}
]
Output
Manipulate[
(*Function to calculate learning rate using Cosine Annealing*)
CosineAnnealingLR[minLR,maxLR,Ti,Tcur_]:=minLR+0.5 (maxLR-minLR)
(1+Cos[(Tcur/Ti) π]);
307
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Output
308
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
epochs=Range[0,Length[lrValues]-1];
Output
Manipulate[
Module[
{lrFunction,initialRate,decayRate,totalIterations,oscillationParam,batchesPerEpoch}
,
(*Define the custom learning rate function combining exponential decay and sine
wave
oscillation*)lrFunction[t_,initialRate_,decayRate_,totalIterations_,oscillationPara
m_,batchesPerEpoch_]:=initialRate Exp[-(decayRate t)/totalIterations]
309
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
lrFunction[t,initialRate,decayRate,totalIterations,oscillationParam,batchesPerEpoch
],
{t,0,totalIterations},
AxesLabel->{"Iteration","Learning Rate"},
PlotRange->{Automatic,{0.005,2.5}},
ImageSize->300
]
],
{{initialRate0,0.59,"Initial learning rate (α₀)"},0,1,0.01},
{{decayRate0,0.6,"Decay rate (ρ)"},0,1,0.01},
{{totalIterations0,50000,"Total iterations (T)"},100,1000000,1000},
{{oscillationParam0,0.05,"Oscillation parameter (τ)"},0,1,0.01},
{{batchesPerEpoch0,10,"Number of batches per epoch (b)"},1,100,1},
ControlPlacement->Left
]
Output
Manipulate[
Module[
{lr,decayFunc,data},
(*Define the decay function*)
decayFunc[t_]:=decayFunc[t-1]*decayFactor^(1/(endEpoch-startEpoch));
310
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
data=Table[{t,lr[t,initialLR,decayFactor,startEpoch,endEpoch,totalEpochs]},{t,1,tot
alEpochs}];
Output
311
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
iteratively update the value of x towards the minimum of the function. Through
interactive controls, users can adjust parameters such as the initial point, number
of steps, learning rate, and momentum parameter, allowing them to observe how
different settings affect the optimization process, convergence speed, and
trajectory: *)
(* Manipulate: *)
Manipulate[
(* Run gradient descent with momentum: *)
path=gradientDescentWithMomentum[targetFunction,functionDerivative,
initialPoint,learningRate,momentumParameter,steps];
(* Manipulate Controls: *)
{{initialPoint,-5,"Initial Point"},-6,6,Appearance->"Labeled"},
{{steps,1,"Steps"},1,50,1,Appearance->"Labeled"},
{{learningRate,0.01,"Learning Rate"},0.001,0.1,Appearance->"Labeled"},
{{momentumParameter,0.95,"Momentum Parameter"},0.1,0.99,Appearance->"Labeled"}
]
312
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Output
functionGradient[x_,y_]=Grad[targetFunction[x,y],{x,y}];
313
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
AppendTo[path,x];
];
(* Return the optimization path: *)
Return[path];
];
(* Visualize: *)
Show[
ContourPlot[
targetFunction[x,y],
{x,-10,10},
{y,-10,10},
Contours->10,
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
ImageSize->300,
PlotLegends->Automatic,
PlotLabel->"Gradient Descent with Momentum",
AspectRatio->Automatic
],
Graphics[
{
Blue,
PointSize[0.015],
Point[path],
Purple,
stepArrows
}
]
]
],
(* Manipulate Controls: *)
{{initialPoint,{-5.3,7.6},"Initial Point"},{-10,-10},{10,10},Appearance-
>"Labeled"},
{{iterations,1,"Iterations"},1,100,1,Appearance->"Labeled"},
{{learningRate,0.001,"Learning Rate"},0.001,0.01,Appearance->"Labeled"},
{{momentumParameter,0.99,"Momentum Parameter"},0.1,0.99,Appearance->"Labeled"},
TrackedSymbols:>{initialPoint,iterations,learningRate,momentumParameter}
]
314
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Output
Manipulate[
Module[
{f,gradient,learningRate,momentum,numIterations,initialGuess,x,v,trajectory},
(* Parameters: *)
learningRate=lr;
momentum=m;
315
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
numIterations=n;
initialGuess={x0,y0};
(* Initialize variables: *)
x=initialGuess;
v={0,0};
(* Update momentum: *)
v=momentum*v-learningRate*grad;
(* Update parameters: *)
x=x+v;
316
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
FrameLabel->{"x1","x2"},
PlotLabel->"Nesterov Accelerated Gradient Descent Trajectory"
]
}
],
(* Controls: *)
{{lr,0.1,"Learning Rate"},0.01,1,0.01},
{{m,0.9,"Momentum"},0,1,0.01},
{{n,1,"Number of Iterations"},1,50,1},
{{x0,1.5,"Initial x1"},-4,4,0.1},
{{y0,-0.5,"Initial x2"},-4,4,0.1}
]
Output
317
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
updatedAccumulatedGradients=MapThread[#1+#2^2&,{accumulatedGradients,gradient}];
{variables,accumulatedGradients}=AdaGradOptimization[grad,learningRate,epsilon,vari
ables,accumulatedGradients];
Manipulate[
(* Initial guess for variables: *)
initialVariables={initialX,initialY};
trajectory=OptimizeWithAdaGrad[initialVariables,learningRate,epsilon,maxIterations]
;
318
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Graphics[
(* Plot arrows to indicate the direction of movement: *)
{Purple,Arrowheads[Small],Arrow/@Partition[trajectory,2,1]}
]
],
319
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
objectiveFunction[x_,y_]=Sin[x]+Cos[y];
{vars,varsSquaredGradients}=RMSProp[grad,lr,decayRate,epsilon,vars,varsSquaredGradi
ents];
Manipulate[
(* Initial guess: *)
initialVars={initialX,initialY};
320
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Contours->10,
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
ImageSize->300
],
Graphics[
(* Plot arrows to indicate the direction of movement: *)
{Purple,Arrowheads[Small],Arrow/@Partition[trajectory,2,1]}
]
],
(* Controls for Manipulate: *)
(* Allow users to adjust initial values, lr, decayRate, epsilon, and
maxIterations:*)
{{initialX,2,"Initial X"},-5,5,Appearance->"Labeled"},
{{initialY,1,"Initial Y"},-5,5,Appearance->"Labeled"},
{{lr,0.1,"Learning Rate"},0.01,1,0.01,Appearance->"Labeled"},
{{decayRate,0.9,"Decay Rate"},0.1,0.99,0.01,Appearance->"Labeled"},
{{epsilon,10^(-6),"Epsilon"},10^(-8),10^(-4),10^(-8),Appearance->"Labeled"},
{{maxIterations,1,"Max Iterations"},1,100,1,Appearance->"Labeled"}
]
Output
321
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
{vars,accumulators,deltas}=AdaDelta[grad,rho,epsilon,vars,accumulators,deltas];
trajectory];
Manipulate[
(* Initial guess: *)
initialVars={initialX,initialY};
(* Perform AdaDelta optimization: *)
322
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
trajectory=OptimizeAdaDelta[initialVars,rho,epsilon,maxIterations];
(* Plot the trajectory with arrows: *)
Show[
ContourPlot[
objectiveFunction[x,y],
{x,-6,6},
{y,-6,6},
PlotLegends->Automatic,
PlotLabel->"Trajectory of AdaDelta Optimization",
Contours->10,
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
ImageSize->300
],
Graphics[
(* Plot arrows to indicate the direction of movement: *)
{Purple,Arrowheads[Small],Arrow/@Partition[trajectory,2,1]}
]
],
(* Controls for Manipulate: *)
(* Allow users to adjust initial values, rho, epsilon, and maxIterations: *)
{{initialX,2,"Initial X"},-5,5,Appearance->"Labeled"},
{{initialY,1,"Initial Y"},-5,5,Appearance->"Labeled"},
{{rho,0.9,"Rho"},0.1,0.99,0.01,Appearance->"Labeled"},
{{epsilon,10^(-6),"Epsilon"},10^(-8),10^(-4),10^(-8),Appearance->"Labeled"},
{{maxIterations,1,"Max Iterations"},1,600,1,Appearance->"Labeled"}
]
Output
323
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
324
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
325
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Manipulate[
(* Initial guess: *)
initialVars={initialX,initialY};
326
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Show[
ContourPlot[
objectiveFunction[x,y],
{x,-5,5},
{y,-5,5},
PlotLegends->Automatic,
PlotLabel->"Trajectory of AdaMax Optimization",
Contours->10,
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
ImageSize->300
],
Graphics[
(* Plot arrows to indicate the direction of movement: *)
{Purple,Arrowheads[Small],Arrow/@Partition[trajectory,2,1]}]
],
(* Controls for Manipulate: *)
{{initialX,2,"Initial X"},-5,5,Appearance->"Labeled"},
{{initialY,1,"Initial Y"},-5,5,Appearance->"Labeled"},
{{lr,0.1,"Learning Rate"},0.001,0.2,0.001,Appearance->"Labeled"},
{{beta1,0.9,"Beta1"},0,1,0.01,Appearance->"Labeled"},
{{beta2,0.999,"Beta2"},0,1,0.001,Appearance->"Labeled"},
{{epsilon,10^(-8),"Epsilon"},10^(-10),10^(-6),10^(-10),Appearance->"Labeled"},
{{maxIterations,1,"Max Iterations"},1,100,1,Appearance->"Labeled"}
]
Output
327
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Manipulate[
(* Initial guess: *)
initialVars={initialX,initialY};
(* Perform AMSGrad optimization: *)
trajectory=OptimizeAMSGrad[initialVars,lr,beta1,beta2,epsilon,maxIterations];
328
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
329
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
{trajectory,{minimizerX,minimizerY,minimumValue}}=NewtonOptimization2D[{initialX,i
nitialY},tolerance,maxIterations];
330
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
PlotLabel->"Optimization Process",
Contours->10,
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
ImageSize->300,
Epilog->{
Blue,
PointSize[0.02],
Point[{minimizerX,minimizerY}],
Purple,
Arrowheads[0.02],
Arrow/@Partition[trajectory,2,1]
}
];
(* Display the plot: *)
plot,
(* Controls for Manipulate: *)
{{initialX,6,"Initial X"},-10,10,0.1,Appearance->"Labeled"},
{{initialY,1.0,"Initial Y"},-10,10,0.1,Appearance->"Labeled"},
{{tolerance,10^(-6),"Tolerance"},10^(-8),1,10^(-8),Appearance->"Labeled"},
{{maxIterations,1,"Max Iterations"},1,30,1,Appearance->"Labeled"}
]
Output
331
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
direction, and updates the solution based on Marquardt's update rule, adjusting the
damping factor accordingly. The Manipulate interface allows users to visualize the
optimization process by adjusting the initial coordinates, damping factor,
tolerance, and maximum iterations through sliders. Finally, it plots the
optimization process and displays the trajectory with arrows indicating the
direction of movement: *)
332
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
plot=ContourPlot[
f[x,y],
{x,-10,10},
{y,-10,10},
PlotLabel->Row[{"Optimization Process"}],
PlotLegends->Automatic,
Contours->10,
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
ImageSize->300,
Epilog->{
Blue,
PointSize[0.02],
Point[{minimizerX,minimizerY}],
Purple,
Arrowheads[0.02],
Arrow/@Partition[trajectory,2,1]}
];
(* Display the plot: *)
plot,
(* Controls for Manipulate: *)
{{initialX,8.0,"Initial X"},-10,10,0.1,Appearance->"Labeled"},
{{initialY,1.0,"Initial Y"},-10,10,0.1,Appearance->"Labeled"},
{{λ,1000.0,"Damping Factor"},0.1,10000,10,Appearance->"Labeled"},
{{tolerance,10^(-6),"Tolerance"},10^(-8),1,10^(-8),Appearance->"Labeled"},
{{maxIterations,1,"Max Iterations"},1,20,1,Appearance->"Labeled"}
]
Output
333
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
334
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Output
(* Optimization method: *)
Method->"QuasiNewton",
AccuracyGoal->20,
PrecisionGoal->20,
WorkingPrecision->20,
335
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Output
336
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Manipulate[
Module[
{minimumPath,trimmedPath},
(*Find the minimum of the objective function using the selected method*)
minimumPath=Reap[
FindMinimum[
(*Objective function to minimize*)
(x^4-16*x^2+5*x)/2+(y^4-16*y^2+5*y)/2,
(*Optimization method*)
Method->Evaluate[method/. {"ConjugateGradient"->"ConjugateGradient",
"Newton"->"Newton",
"QuasiNewton"->"QuasiNewton"
}],
AccuracyGoal->20,
PrecisionGoal->20,
WorkingPrecision->40,
(*Record optimization steps*)
StepMonitor:>Sow[{x,y}]
]
][[2,1]];
337
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Output
338
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Unit 6.2
Optimizing Neural Networks with Learning Rate
Schedules and Adaptive Algorithms in Mathematica
In Mathematica, NetTrain is a part of the neural network framework, which allows you to train neural networks
easily. You can specify additional options to customize the training process. The Method option in NetTrain is indeed
crucial for customizing the optimization algorithm used during training. It allows you to choose the specific
optimization algorithm that best suits your neural network and training data.
For the method "SGD", the following additional suboptions are supported:
"Momentum" 0.93 how much to preserve the previous step when updating the derivative
For the method "ADAM", the following additional suboptions are supported:
"Beta1" 0.9 exponential decay rate for the first moment estimate
"Beta2" 0.999 exponential decay rate for the second moment estimate
"Epsilon" 0.00001` stability parameter
For the method "RMSProp", the following additional suboptions are supported:
"Beta" 0.95 exponential decay rate for the moving average of the gradient magnitude
"Epsilon" 0.000001 stability parameter
"Momentum" 0.9 momentum term
Suboptions for specific methods can be specified using Method->{"method",opt1->val1,…}. The following
suboption is supported for all methods:
"LearningRateSchedule" Automatic how to scale the learning rate as training progresses
In Mathematica’s NetTrain function, the "LearningRateSchedule" option allows for dynamic adjustment of the
learning rate during training. The learning rate for each batch is calculated as
initial * f[batch, total],
where: initial is the initial learning rate specified using the "LearningRate" option.
f is a function that takes two arguments: batch and total.
batch is the current batch number.
total is the total number of batches that will be visited during training.
The value returned by f should be a number between 0 and 1, representing the scale by which to adjust the initial
learning rate for the current batch. You can customize the f function to implement different learning rate schedules
according to your specific requirements, such as step decay, linear decay, or custom schedules based on the training
progress. Adjusting the learning rate dynamically can help improve the convergence and performance of the neural
network during training.
339
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
340
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
(* Step decay: αt = α0 ∗ d⌊t/s⌋ , α_0=0.3 is the initial learning rate, d=0.9 or d=0.5 is
the constant factor (drop factor or decay factor) by which the learning rate drops
each time, s=1000 is the step size, indicating after how many iterations the learning
rate should be decayed: *)
decaySchedule1[b_,bmax_]:=0.9^Floor[b/1000];
decaySchedule2[b_,bmax_]:=0.5^Floor[b/1000];
Output
341
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
{
10,LogisticSigmoid,
5,LogisticSigmoid,
5,LogisticSigmoid,
1
},
(* Input layer with 2 neurons representing 2D input points: *)
"Input"->2
];
(* Exponential Decay: α_t=α_0 e^(-d*t), d is the decay rate parameter. Note that,
we used "Interval"->"Batches" not "Interval"->"Rounds": *)
342
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
decaySchedule1=generateSchedule[0.001];
decaySchedule2=generateSchedule[0.01];
ListPlot[
{loss1,loss2},
PlotRange->Full,
Mesh->All,
Joined->True,
PlotStyle->{Opacity[0.9],Opacity[0.5]},
PlotLabel->"Loss Evolution Over Batches",
PlotLegends-> {"Loss of Schedule 1","Loss of Schedule 2"},
ImageSize->300 ,
AxesLabel->{"Batches","Loss"}
]
Output
Output
343
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
344
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
initial is the initial learning rate specified using the LearningRate option. The
value returned by f should be a number between 0 and 1: *)
decaySchedule1[b_,bmax_]:=(1-b/bmax)^0.5;
decaySchedule2[b_,bmax_]:=(1-b/bmax)^1.8;
Output
345
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
5,LogisticSigmoid,
1
},
(* Input layer with 2 neurons representing 2D input points: *)
"Input"->2
];
346
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
x=Abs[b/stepsize-2*cycle+1];
baseLR+(maxLR-baseLR)*Max[0,(1-x)]
]
]
ListPlot[
{loss1,loss2},
PlotRange->Full,
Mesh->All,
Joined->True,
PlotLabel->"Loss Evolution Over Rounds",
PlotLegends-> {"Loss of Schedule 1","Loss of Schedule 2"},
ImageSize->300 ,
AxesLabel->{"Rounds","Loss"}
]
Output
347
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Output
348
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
LearningRate->0.1,
(* Use a batch size of 1024: *)
BatchSize->1024,
(* Use ADAM optimization method with specified Parameters
(beta1,beta2,epsilon): *)
Method->{method,"Beta1"->beta1,"Beta2"->beta2,"Epsilon"->0.00001}
];
Output
349
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
350
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Output
Mathematica Code 6.32 ADAM, RMSProp, SGD, with step decay and triangular schedule (NN)
Input (* The code aims to train a neural network on generated example data by comparing
the performance of different optimization methods and learning rate schedules. It
first generates training data based on a predefined function and defines a neural
network architecture. The network is then initialized with appropriate weights using
Kaiming initialization. The code proceeds to train the network using various
optimization methods (ADAM, RMSProp, SGD) and learning rate schedules (step decay,
triangular schedule) while monitoring training progress by tracking loss function
evolution and learning rate changes. The goal is to visualize and analyze how
different optimization strategies impact the training process, facilitating the
identification of the most effective approach for the given dataset and network
architecture: *)
351
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
(* Step decay: αt = α0 ∗ d⌊t/s⌋ , α_0=0.3 is the initial learning rate, d=0.9 is the
constant factor (drop factor or decay factor) by which the learning rate drops each
time,s=1000 is the step size, indicating after how many iterations the learning rate
should be decayed.*)
decaySchedule1[b_,bmax_]:=0.9^Floor[b/1000];
generateSchedule[baseLR_,maxLR_,stepsize_]:=Module[
{cycle,x},
Function[
{b,bmax},
cycle=Floor[1+b/(2*stepsize)];
x=Abs[b/stepsize-2*cycle+1];
baseLR+(maxLR-baseLR)*Max[0,(1-x)]
]
]
decaySchedule2=generateSchedule[0.1,1,500];
352
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
{loss1,result1,loss2,result2,loss3,result3,loss4,result4,loss5,result5,loss6,result
6}=Flatten[
trainNetwork@@@{
{"ADAM",decaySchedule1},
{"RMSProp",decaySchedule1},
{"SGD",decaySchedule1},
{"ADAM",decaySchedule2},
{"RMSProp",decaySchedule2},
{"SGD",decaySchedule2}
},1];
ListPlot[
{loss1,loss2,loss3,loss4,loss5,loss6},
PlotRange->Full,
Mesh->All,
Joined->True,
PlotLabel->"Loss Evolution Over Rounds",
PlotLegends-> {
"Loss with ADAM and Schedule 1",
"Loss with RMSProp and Schedule 1",
"Loss with SGD and Schedule 1",
"Loss with ADAM and Schedule 2",
"Loss with RMSProp and Schedule 2",
"Loss with SGD and Schedule 2"
},
ImageSize->300 ,
AxesLabel->{"Rounds","Loss"}
]
Output
353
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
Output
354
CHAPTER 6 LEARING RATE SCHEDULES AND GRADIENT DESCENT VARIANTS
355
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
CHAPTER 7
STRATEGIES FOR GENERALIZATION AND HYPER-
PARAMETER TUNING
Remark:
This chapter provides a Mathematica implementation of the concepts and ideas presented in Chapter 6, [1], of the
book titled Artificial Neural Network and Deep Learning: Fundamentals and Theory. We strongly recommend that
you begin with the theoretical chapter to build a solid foundation before exploring the corresponding practical
implementation.
In this chapter, we delve into some of the most critical concepts and methodologies that form the backbone of machine
learning, guiding the development of models that are not only powerful but also robust and generalizable across
various scenarios. We focus on the aspects of Neural Network (NN) training that determine how effectively a model
can generalize from training data to unseen data. Generalization is the ultimate test of a NN's performance, assessing
its ability to apply learned patterns to new datasets.
• We begin by addressing the fundamental challenges of overfitting and generalization. Overfitting occurs
when the NN learns the details and noise in the training data to an extent that it negatively impacts the
performance of NN on new data. Conversely, generalization refers to the model's ability to apply what it has
learned to unseen data. We will discuss strategies to balance this, including the importance of a robust model
architecture.
• Next, we explore the bias-variance trade-off, a pivotal concept that helps in diagnosing the performance of
machine learning algorithms. Bias refers to errors due to overly simplistic assumptions in the learning
algorithm. Variance refers to errors from sensitivity to small fluctuations in the training set. High bias can
cause a model to miss the relevant relations between features and target outputs (underfitting), whereas high
variance can cause modeling the random noise in the training data (overfitting).
• To assess a model's generalization, we will split the data into three sets: training, validation, and testing [31-
38]. The training set is used to train the model, the validation set is used to tune the model's hyperparameters
and prevent overfitting, and the test set is used to evaluate the model's performance as it simulates real-world,
unseen data.
• As we measure the success of our models, performance measures come into play. Common metrics [94-99]
include accuracy, precision, recall, the F1 score for classification tasks, and mean squared error or mean
absolute error for regression tasks. We will explore how these metrics can guide hyperparameter tuning.
• The practice of tuning hyperparameters is essential for optimizing model performance [100-108]. Techniques
such as grid search and random search are popular methods for exploring the hyperparameter space. Grid
search evaluates the model across a grid of hyperparameter combinations, while random search randomly
selects combinations, offering a balance between exploration and exploitation.
• Gaussian processes (GPs) [109-126] are a probabilistic model used in machine learning to predict the
distribution of possible outcomes rather than just the best estimate. GPs are particularly useful for
understanding model uncertainty, which can be leveraged for Bayesian optimization (BO) in hyperparameter
tuning.
• Further enhancing our toolkit for hyperparameter optimization, we will introduce tuning hyperparameters
with BO. BO is a strategy for the global optimization of objective functions that are noisy, expensive to
evaluate, or have no closed form. It is particularly useful for tuning hyperparameters in scenarios where
356
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
evaluations are costly or time-consuming. BO uses past evaluation results to form a probabilistic model
mapping hyperparameters to a probability of a score on the objective function.
• Lastly, we will discuss Acquisition Functions (ACFs). ACFs in BO are used to select the next set of
hyperparameters to evaluate. Common ACFs include Expected Improvement (EI), Probability of
Improvement (PI), and Upper Confidence Bound (UCB). These functions help in deciding which
hyperparameter settings are likely to yield improvements over the best current observations.
In this chapter, by leveraging Mathematica’s advanced functionalities, we will explore various techniques to optimize
our models and enhance their predictive capabilities. The chapter is structured into five distinct units, each designed
to progressively deepen the reader's understanding and proficiency in constructing and optimizing NNs using
Mathematica. From exploring the fundamental challenges of overfitting to mastering advanced techniques like BO,
this chapter provides a step-by-step guide to refining predictive models and enhancing their performance in real-world
scenarios.
By the end of this chapter, readers will be equipped with a deep understanding and practical skills to leverage
Mathematica for building and optimizing NNs, ready to tackle complex real-world data challenges.
357
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Unit 7.1
The Fundamentals of Overfitting: What It Is and Why It
Happens
(* Plot the training data with the original sinusoidal function curve: *)
ListPlot[
trainingData,
PlotStyle->{PointSize[0.025],Purple},
PlotRange->{{0,1},{-1.5,1.5}},
FrameLabel->{"x","y"},
AxesOrigin->{0,0},
ImageSize->270,
Epilog->{Blue,Thick,Line[Transpose[{Range[0,1,0.01],Sin[2 π
Range[0,1,0.01]]}]]}
]
358
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
],
Plot[
fittedPolynomials[[i]],
{x,0,1},
PlotStyle->Blue
],
PlotRange->All,
AxesLabel->{"x","y"},
PlotLabel->"Fitted Polynomial of Degree "<>ToString[{0,1,3,9}[[i]]]
],
{i,Length[fittedPolynomials]}
]
Output
Output
SeedRandom[12];
359
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
360
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
361
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output
362
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
ListPlot[
trainingData,
PlotStyle->{PointSize[0.025],Purple},
PlotRange->All,
ImageSize->250
],
Plot[
Evaluate[fittedPolynomials],
{x,0,1},
PlotLegends->Placed[{"M=1","M=3","M=9"},{0.7,0.8}]
],
PlotRange->Full,
AxesLabel->{"x","y"},
PlotLabel->"Fitted Polynomial of Degree "<>ToString[degrees]"\n for Dataset
"<>ToString[dataNo]
]
363
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Generate synthetic noisy training data based on a Gaussian function and add
Gaussian noise: *)
trainingData=Table[
(* Apply noise with standard deviation of 0.15: *)
x->Exp[-x^2]+RandomVariate[NormalDistribution[0,.15]],
{x,-3,3,.2}
];
(* Visualize the training data and the noise-free original function for comparison:
*)
(* Plot the training data with red points: *)
trainingPlot=ListPlot[
List@@@trainingData,
PlotStyle->Red,
ImageSize->250,
AxesLabel->{"x","y"},
PlotLabel->"Training Data"
];
(* Train the MLP on the generated training data, limiting the training time to 30
seconds: *)
trainingResults=NetTrain[mlp,trainingData,All,TimeGoal->30]
(* Plot predictions from the trained model against the original training data: *)
364
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
predictedTrainingPlot=Plot[
trainedNet[x],
{x,-3,3},
ImageSize->250,
AxesLabel->{"x","y"},
PlotLabel->"Trained Model Prediction"
];
Show[predictedTrainingPlot,trainingPlot]
(* Visualize how the trained model performs on new, unseen (test) data: *)
predictedTestPlot=Plot[
trainedNet[x],
{x,-3,3},
ImageSize->250,
AxesLabel->{"x","y"},
PlotLabel->"Trained Model Prediction on Test Data"
];
(* Show both the test data and the model's predictions on the same plot to evaluate
accuracy: *)
Show[predictedTestPlot,testPlot]
Output
365
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output 0.00446618
Output
Output
366
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Unit 7.2
Performance Metrics
In Mathematica, ValidationSet is an option used in functions like NetTrain, Predict, and Classify. It's utilized
for specifying a dataset that the neural network or machine learning model will not use for training but instead use for
validation during the training process. This helps in assessing how well the model generalizes to unseen data and
avoids overfitting.
TrainingProgressMeasurements is another option used in functions like NetTrain to specify what training progress
metrics should be computed and returned during the training process. These metrics can include things like loss values,
accuracy, etc. It allows you to monitor the progress of your training and make decisions accordingly, such as whether
to stop training or adjust parameters.
NetTrainResultsObject is the output object returned by the NetTrain function in Mathematica after training a
neural network. It contains various pieces of information about the training process and the trained network, such as
final training and validation loss, training time, the trained neural network itself, etc. This object can be further used
for evaluation, testing, or deployment of the trained model.
ValidationMeasurements is an option used in functions like Predict, Classify, and NetTrain. It allows you to
specify what measurements you want to compute on the validation set during the evaluation of a trained model.
1. Validation Set
ValidationSet
is an option for Predict, Classify, NetTrain, and related functions that specifies the validation set to be used
during the training phase.
Remarks:
• With ValidationSet->data, model and hyperparameter selections are done by testing performance on data.
data can be given in any format allowed for the training set.
• With ValidationSet->Automatic, cross-validation methods on the original data supplied to Predict,
Classify, etc. will be used instead.
• ValidationSet->data is typically used when the data in the training set and the data that one wishes to
predict or classify come from different sources.
• If a validation set is specified, NetTrain will return the net that produced the lowest validation loss during
training with respect to this set.
None use only the existing training set to estimate loss (default)
data validation set in the same form as training data
Scaled[frac] reserve a specified fraction of the training set for validation
{spec,"Interval"->int} specify the interval at which to calculate validation loss
TrainingProgressMeasurements
is an option for NetTrain that specifies measurements to make while training is in progress.
For nets that contain a CrossEntropyLossLayer, the following built-in measurements are available:
367
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
For nets that contain a MeanSquaredLossLayer or MeanAbsoluteLossLayer, the following built-in measurements are
available:
Remarks:
• NetTrain[net,data,All] returns a NetTrainResultsObject[…] that contains values for all properties that
do not require significant additional computation or memory.
• NetTrainResultsObject[…][prop] is used to look up property prop from the NetTrainResultsObject.
• Associations of the final value of all measurements can be obtained after training by specifying
"RoundMeasurements" and "ValidationMeasurements" as properties in
NetTrain[net,data,properties] or in a NetTrainResultsObject.
368
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Remark:
NetTrain[net,data,{prop1,prop2,…}] returns a list of the results for the propi.
(* Generate training data: sample points from the defined function and add Gaussian
noise: *)
trainingData=Table[
x->dataFunction[x]+RandomVariate[NormalDistribution[0,noiseLevel]],
{x,-3,3,0.01}
];
(* Generate validation data in the same manner but with fewer points: *)
validationData=Table[
x->dataFunction[x]+RandomVariate[NormalDistribution[0,noiseLevel]],
{x,-3,3,0.1}
];
(* Define a neural network with two hidden layers and one output layer: *)
net=NetChain[
{
(* First hidden layer with 50 neurons and Tanh activation: *)
LinearLayer[50],Tanh,
(* Second hidden layer with 30 neurons and Tanh activation: *)
LinearLayer[30],Tanh,
(* Output layer with 1 neuron: *)
LinearLayer[1]
}
];
369
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
netTrainResults=NetTrain[
net,
trainingData,
All,
ValidationSet->validationData,
TrainingProgressMeasurements-
>{"MeanDeviation","MeanSquare","RSquared","StandardDeviation"},
MaxTrainingRounds->50
]
Output
(* Generate training data: sample points from the defined function and add
Gaussian noise: *)
trainingData=Table[
x->dataFunction[x]+RandomVariate[NormalDistribution[0,noiseLevel]],
{x,-3,3,0.01}
];
(* Generate validation data in the same manner but with fewer points: *)
validationData=Table[
x->dataFunction[x]+RandomVariate[NormalDistribution[0,noiseLevel]],
{x,-3,3,0.1}
];
370
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Define a neural network with two hidden layers and one output layer: *)
net=NetChain[
{
(* First hidden layer with 50 neurons and Tanh activation: *)
LinearLayer[50],Tanh,
(* Second hidden layer with 30 neurons and Tanh activation: *)
LinearLayer[30],Tanh,
(* Output layer with 1 neuron: *)
LinearLayer[1]
}
];
(* Extract and list all properties available from the training results: *)
netTrainResults["Properties"]
(* Find the training round with the best (lowest) validation loss: *)
minPosition1=netTrainResults["BestValidationRound"]
minPosition2=Position[validationLossList,Min[validationLossList]]
minPosition3=Position[validationMeasurementsLists[[1]],Min[validationMeasurements
Lists[[1]]]]
(* Get the most recent validation loss from the final training round: *)
mostRecentValidationLoss1=netTrainResults["ValidationLoss"]
(* Get the most recent validation loss and Validation Measurements from the final
training round: *)
mostRecentValidationLoss1=Values[netTrainResults["ValidationMeasurements"]]
371
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Visualize the model's predictions along with the actual test data: *)
plotModel=Plot[
trainedNet[x],
{x,-3,3},
PlotStyle->{Purple,Thick},
PlotLegends->{"Model"}
];
plottestData=ListPlot[
List@@@testData,
PlotStyle->Orange,
PlotLegends->{"Test Data"}
];
Output {ArraysLearningRateMultipliers,BatchesPerRound,BatchesPerSecond,BatchLossList,Bat
chMeasurements,BatchMeasurementsLists,BatchSize,BestValidationRound,Checkpointing
Files,ExamplesProcessed,FinalLearningRate,FinalPlots,InitialLearningRate,Internal
VersionNumber,LossPlot,MeanBatchesPerSecond,MeanExamplesPerSecond,NetTrainInputFo
rm,OptimizationMethod,ReasonTrainingStopped,RoundLoss,RoundLossList,RoundMeasurem
ents,RoundMeasurementsLists,RoundPositions,SkippedTrainingData,TargetDevice,Total
Batches,TotalRounds,TotalTrainingTime,TrainedNet,TrainingExamples,TrainingNet,Tra
iningUpdateSchedule,ValidationExamples,ValidationLoss,ValidationLossList,Validati
onMeasurements,ValidationMeasurementsLists,ValidationPositions}
Output
Output 46
Output {{46}}
Output {{46}}
Output 0.0183498
Output 0.0183498
Output 0.0192765
Output {0.0192765,0.111954,0.0192765,0.86395,0.13884}
Output
Loss->
372
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
MeanDeviation->
MeanSquare->
RSquared->
StandardDeviation->
373
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Generate training data: sample points from the defined function and add Gaussian
noise: *)
trainingData=Table[
x->dataFunction[x]+RandomVariate[NormalDistribution[0,noiseLevel]],
{x,-3,3,0.01}
];
(* Generate validation data in the same manner but with fewer points: *)
validationData=Table[
x->dataFunction[x]+RandomVariate[NormalDistribution[0,noiseLevel]],
{x,-3,3,0.1}
];
374
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* The code aims to generate a synthetic dataset within a unit disk, label the data
based on proximity to the center, and visualize this distribution. It constructs a
simple neural network for binary classification, which includes linear and non-
linear layers to capture complex patterns. The network is trained using the
generated data, validated with a separate set, and evaluated using several
performance metrics. The training process is visualized through a contour plot
showing the decision boundaries and other training-related plots like the confusion
matrix. The goal is to demonstrate the complete workflow of data preparation, model
training, and performance evaluation in a neural network application: *)
(* Assign labels based on whether the point's distance from the origin is less than
0.5: *)
trainlabels=Thread[Map[Norm,trainpoints]<0.5];
(* Assign labels using the same criteria as for the training set: *)
validationLabels=Thread[Map[Norm,validationPoints]<0.5];
(* Visualize the synthetic training set with different colors for each class: *)
ListPlot[
{
Pick[trainpoints,trainlabels,True],
Pick[trainpoints,trainlabels,False]
},
AspectRatio->1,
ImageSize->250,
PlotStyle->PointSize[Medium],
FrameLabel->{"X","Y","Synthetic Training Set"},
PlotLegends->{"Class 1","Class 2"}
]
(* Define a neural network with two linear layers and activation functions: *)
net=NetChain[
{
LinearLayer[20],ElementwiseLayer[Tanh],
LinearLayer[],ElementwiseLayer[LogisticSigmoid]},
"Output"->NetDecoder["Boolean"]
]
(* Train the neural network on the training data with specified metrics and
validation: *)
netTrainResults=NetTrain[
net,
trainingData,
All,
375
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
ValidationSet->validationData,
TrainingProgressMeasurements->{
"FalseNegativeNumber","FalsePositiveNumber","TrueNegativeNumber",
"TruePositiveNumber","Accuracy","F1Score",
"MatthewsCorrelationCoefficient","Precision","Recall",
"ScottPi","ConfusionMatrixPlot"
}
]
Output
Output
376
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output <|Loss->0.0811929,FalseNegativeNumber->6.,FalsePositiveNumber-
>0.,TrueNegativeNumber->368.,TruePositiveNumber->126.,Accuracy->0.988,F1Score-
>0.976744,MatthewsCorrelationCoefficient->0.96914,Precision->1.,Recall-
>0.954545,ScottPi->0.968658,ConfusionMatrixPlot->{
|>
377
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output
Output
<|Loss-> ,
FalseNegativeNumber-> ,
FalsePositiveNumber-> ,
378
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
TrueNegativeNumber-> ,
TruePositiveNumber-> ,
Accuracy-> ,
F1Score-> ,
MatthewsCorrelationCoefficient->
379
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Precision-> ,
Recall-> ,
ScottPi-> ,
380
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
ConfusionMatrixPlot-> |>
(* Assign labels based on whether the point's distance from the origin is less
than 0.5: *)
trainlabels=Thread[Map[Norm,trainpoints]<0.5];
381
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Assign labels using the same criteria as for the training set: *)
validationLabels=Thread[Map[Norm,validationPoints]<0.5];
(* Define a neural network with two linear layers and activation functions: *)
net=NetChain[
{
LinearLayer[20],ElementwiseLayer[Tanh],
LinearLayer[],ElementwiseLayer[LogisticSigmoid]},
"Output"->NetDecoder["Boolean"]
]
(* Train the neural network on the training data with specified metrics and
validation: *)
netTrainResults=NetTrain[
net,
trainingData,
"ValidationMeasurements",
ValidationSet->validationData,
TrainingProgressMeasurements->{
"FalseNegativeNumber","FalsePositiveNumber","TrueNegativeNumber",
"TruePositiveNumber","Accuracy","F1Score",
"MatthewsCorrelationCoefficient","Precision","Recall",
"ScottPi","ConfusionMatrixPlot"
}
]
Output <|Loss->0.110256,FalseNegativeNumber->12.,FalsePositiveNumber-
>0.,TrueNegativeNumber->370.,TruePositiveNumber->118.,Accuracy->0.976,F1Score-
>0.951613,MatthewsCorrelationCoefficient->0.937645,Precision->1.,Recall-
>0.907692,ScottPi->0.935655,ConfusionMatrixPlot->
|>
382
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Unit 7.3
Gaussian Processes Implementation in Mathematica
From Scratch
(* Define a mean vector for the multivariate distribution, initializing all elements
to zero: *)
zeroMeanVector={0,0,0,0,0};
(* Define the multivariate normal distribution using the zero mean vector and
correlation matrix. This distribution will be used to generate random samples: *)
multivariateDistribution=MultinormalDistribution[zeroMeanVector,correlationMatrix
];
383
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
SeedRandom[1];
(* Plot the generated random samples as discrete functions over integer points
{1,2,3,4,5}: *)
ListPlot[
Transpose[{Range[5],#}]&/@randomSamples,
Joined->True,
PlotMarkers->"OpenMarkers",
ImageSize->250,
PlotLabel->"Random Discrete Functions",
Frame->{True,True,False,False},
Axes->False,
PlotLegends->{"Sample 1","Sample 2","Sample 3","Sample 4","Sample 5","Sample
6"},
FrameLabel->{"Index","Value"}
]
Output
Output
384
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Manipulate[
Module[
{zeroMeanVector,correlationMatrix,multivariateDistribution,randomSamples,matrixPl
ot,samplesPlot},
(* Define the multivariate normal distribution with the given mean and covariance
matrix: *)
multivariateDistribution=MultinormalDistribution[zeroMeanVector,correlationMatrix
];
(* Plot the generated random samples as discrete functions over integer points
{1,2,3,4,5}: *)
samplesPlot=ListPlot[
Transpose[{Range[5],#}]&/@randomSamples,
Joined->True,
PlotMarkers->"OpenMarkers",
ImageSize->250,
PlotLabel->"Random Discrete Functions",
Frame->{True,True,False,False},
Axes->False
];
385
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
{{corr4,0,"Fourth Correlation"},0,1,0.01},
{{numSamples,6,"Number of Samples"},1,10,1}
]
Output
(* Compute the covariance matrix for the set of input points using the squared
exponential covariance function. This matrix quantifies the expected degree of
similarity between any two points based on their squared exponential relationship:
*)
covarianceMatrix=Outer[SquaredExponentialCovariance,inputPoints,inputPoints];
(* Add a small value to the diagonal elements (nugget effect) to ensure the matrix
is numerically stable and positive definite: *)
covarianceMatrix=covarianceMatrix+10^-6*IdentityMatrix[numberOfPoints];
386
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Visualize the covariance matrix using MatrixPlot, providing insights into how
covariance changes with the distance between points: *)
MatrixPlot[
covarianceMatrix,
ImageSize->250,
PlotLabel->"Covariance Matrix Visualization",
PlotLegends->Automatic
]
(* Display the sampled functions from the Gaussian Process, illustrating the range
of variation among functions consistent with the specified covariance: *)
Show[
ListLinePlot[
Transpose[{inputPoints,#}]&/@sampledFunctions,
Axes->None,
Filling->None,
Frame->{True,True,False,False},
FrameLabel->{"Input X","Function Value"},
PlotLabel->"Samples From Gaussian Process with\n Squared Exponential
Covariance",
PlotLegends->Array["Sample "<>ToString[#]&,6],
ImageSize->300
],
ListLinePlot[
Transpose[{inputPoints,meanVector}],
PlotStyle->Black,
PlotLegends->{"Mean Function"}
]
]
Output
387
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
(* Create a covariance matrix for a given scale parameter. This matrix is computed
by applying the squared exponential covariance function to every pair of input
points, which quantifies the expected degree of similarity based on their distance
and the scale. A small constant (nugget effect) is added to the diagonal elements
to ensure numerical stability by making the matrix positive definite: *)
CovarianceMatrix[scale_]:=Outer[SquaredExponentialCovariance[scale,#1,#2]&,input
Points,inputPoints]+10^-6*IdentityMatrix[numberOfPoints];
sampledFunctions=RandomVariate[MultinormalDistribution[meanVector,covarianceMatri
x],samples];
388
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
389
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Mean vector for the multivariate normal distribution, assumed zero for
simplicity: *)
meanVector=ConstantArray[0,numberOfPoints];
390
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
PlotLegends->Array["Sample "<>ToString[#]&,samples],
ImageSize->300
],
(* Overlay the mean function plot: *)
ListLinePlot[
Transpose[{inputPoints,meanVector}],
PlotStyle->Black,
PlotLegends->{"Mean Function"}
]
];
{matrixPlot,functionPlot}];
Output
391
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Training input locations, uniformly spaced within one period of a sine wave: *)
trainingInputs=Transpose[{Subdivide[0,2 Pi,numTraining-1]}];
(* Covariance matrix for the training data using a squared exponential kernel: *)
covarianceMatrixTraining=Exp[-
trainingDistMatrix]+DiagonalMatrix[ConstantArray[stabilityEpsilon,numTraining]];
(* Test input locations, extending slightly beyond the training input range: *)
testInputs=Transpose[{Subdivide[-0.5,2 Pi+0.5,70]}];
MatrixPlot[
Transpose[crossCovarianceMatrix],
ImageSize->Small,
AspectRatio->1/2
]
392
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
inverseCovarianceMatrix=Inverse[covarianceMatrixTraining];
393
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
]
],
ListPlot[
Transpose[{Flatten[trainingInputs],Flatten[trainingOutputs]}],
PlotMarkers->{"OpenMarkers",10},
PlotStyle->Black,
PlotLegends->{"Training Data"}
],
ImageSize->300
]
Output
Output
Output
Output
Output
394
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Compute the initial covariance matrix using the squared exponential kernel for
all pairs of evaluation points: *)
initialCovariance=Outer[SquaredExponentialKernel,evaluationPoints,evaluationPoint
s];
(* Apply a nugget effect to ensure the covariance matrix is numerically stable and
positive definite: *)
stabilizedCovariance=initialCovariance+10^-6*IdentityMatrix[totalPoints];
(* Adjust the covariance matrix to reflect conditioning on the training data. This
matrix represents the updated belief about point correlations after observing the
training data: *)
conditionedCovariance=stabilizedCovariance-
stabilizedCovariance[[All,trainingIndex]].Inverse[stabilizedCovariance[[trainingI
ndex,trainingIndex]]].stabilizedCovariance[[trainingIndex,All]];
conditionedCovariance=conditionedCovariance+10^-6*IdentityMatrix[totalPoints];
395
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Visualize the conditioned covariance matrix. This plot provides insights into
how the knowledge of the training data influences the correlations across the
process: *)
MatrixPlot[
conditionedCovariance,
ImageSize->250,
PlotLabel->"Conditioned Covariance Matrix",
PlotLegends->Automatic
]
(* Compute the predictive mean of the Gaussian Process at each point, given the
training data: *)
predictiveMean=initialCovariance[[All,trainingIndex]].Inverse[initialCovariance[[
trainingIndex,trainingIndex]]].trainingOutput;
sampledFunctions=RandomVariate[
MultinormalDistribution[predictiveMean,conditionedCovariance],
6
];
(* Visualize the sampled functions, the mean prediction, and the training data in
a composite plot. This illustrates the variability of the Gaussian Process and its
adherence to the known data: *)
Show[
ListPlot[
Map[Transpose[{evaluationPoints,#}]&,sampledFunctions],
Joined->True,
Axes->None,
Frame->{True,True,False,False},
FrameLabel->{"x","y"},
PlotLabel->"Sampled Functions from Conditioned\n Gaussian Process",
ImageSize->250
],
ListPlot[
Transpose[{Part[evaluationPoints,trainingIndex],trainingOutput}],
PlotMarkers->"OpenMarkers",
PlotStyle->Black,
PlotLegends->{"Training Data"},
ImageSize->250
],
ListLinePlot[
Transpose[{evaluationPoints,predictiveMean}],
PlotStyle->Directive[GrayLevel[0],Opacity[1]],
PlotLegends->{"Predictive Mean"},
ImageSize->250
]
]
396
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output
Manipulate[
(* Define the squared exponential kernel: *)
SquaredExponentialKernel[x1_,x2_]:=Exp[-(x1-x2)^2];
(* Compute the initial covariance matrix using the squared exponential kernel for
all pairs of evaluation points: *)
initialCovariance=Outer[SquaredExponentialKernel,evaluationPoints,evaluationPoint
s];
397
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Adjust the covariance matrix to reflect conditioning on the training data. This
matrix represents the updated belief about point correlations after observing the
training data: *)
conditionedCovariance=stabilizedCovariance-
stabilizedCovariance[[All,trainingIndex]].Inverse[stabilizedCovariance[[trainingI
ndex,trainingIndex]]].stabilizedCovariance[[trainingIndex,All]];
conditionedCovariance=conditionedCovariance+10^-6*IdentityMatrix[totalPoints];
(* Visualize the conditioned covariance matrix. This plot provides insights into
how the knowledge of the training data influences the correlations across the
process: *)
matrixPlot=MatrixPlot[
conditionedCovariance,
ImageSize->250,
PlotLabel->"Conditioned Covariance Matrix",
PlotLegends->Automatic
];
(* Compute the predictive mean of the Gaussian Process at each point, given the
training data: *)
predictiveMean=initialCovariance[[All,trainingIndex]].Inverse[initialCovariance[[
trainingIndex,trainingIndex]]].{trainingOutput};
sampledFunctions=RandomVariate[MultinormalDistribution[Flatten[predictiveMean],co
nditionedCovariance],numSamples];
(* Visualize the sampled functions, the mean prediction, and the training data in
a composite plot. This illustrates the variability of the Gaussian Process and its
adherence to the known data: *)
functionsPlot=Show[
ListPlot[
Map[Transpose[{evaluationPoints,#}]&,sampledFunctions],
Joined->True,
Axes->None,
Frame->{True,True,False,False},
FrameLabel->{"x","y"},
PlotLabel->"Sampled Functions from Conditioned\n Gaussian Process",
ImageSize->250
],
ListPlot[
Transpose[{Part[evaluationPoints,trainingIndex],{trainingOutput}}],
PlotMarkers->"OpenMarkers",
PlotStyle->Black,
PlotLegends->{"Training Data"},
ImageSize->250
],
398
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
ListLinePlot[
Transpose[{evaluationPoints,predictiveMean}],
PlotStyle->Directive[GrayLevel[0],Opacity[1]],
PlotLegends->{"Predictive Mean"},
ImageSize->250
]
];
{matrixPlot,functionsPlot},
Output
(* Define the squared exponential covariance function between any two points x1
and x2: *)
SquaredExponential[x1_,x2_]:=Exp[-(x1-x2)^2];
399
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
stabilizedCovariance=initialCovariance+10^-6*IdentityMatrix[numPoints];
conditionedCovariance=conditionedCovariance+IdentityMatrix[numPoints]/10^6;
(* Display the sampled functions, with training data points and the predicted mean
function: *)
Show[
ListPlot[
Map[Transpose[{evaluationPoints,#}]&,sampledPaths],
Axes->None,
Filling->None,
Frame->{True,True,False,False},
FrameLabel->{"Input Position","Function Value"},
PlotLabel->"Realizations from a Conditioned \n Gaussian Process",
Joined->True,
ImageSize->250
],
ListPlot[
Transpose[{evaluationPoints[[trainingIndices]],trainingOutputs}],
PlotMarkers->"OpenMarkers",
PlotStyle->Black,
PlotLegends->{"Observed Data"}
],
ListLinePlot[
Transpose[{evaluationPoints,conditionalMean}],
PlotStyle->Directive[Black,Thick],
400
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
PlotLegends->{"Predicted Mean"}
]
]
Output
Output
Output
Output
Output
401
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Unit 7.4
Setting Up Bayesian Optimization in Mathematica
Bayesian optimization is a powerful strategy for the optimization of objective functions that are expensive to evaluate.
It is particularly useful in scenarios where acquiring new data points is costly or experiments take a long time. This
unit provides a practical guide to implementing Bayesian optimization in Mathematica using several of its built-in
functions: Predict, GaussianProcess, BayesianMinimization, and BayesianMaximization.
• The Predict function in Mathematica is a high-level machine learning function used to create predictive
models from data. It automatically selects the appropriate machine learning algorithm based on the nature of
the data provided. This function can handle various types of data, including numeric, categorical, and textual
data, making it versatile for a range of predictive tasks. Once trained, the model can be used to make
predictions on new data. It supports different prediction methods like linear regression, decision trees, neural
networks, and more, depending on the structure and complexity of the data.
• In Mathematica, GaussianProcess can indeed be used as a method within the Predict function. This
approach allows you to utilize Gaussian process models for predictive tasks.
• BayesianMinimization is a function in Mathematica that applies Bayesian optimization techniques to find
the minimum of a function. This method is useful for optimization problems where evaluations of the function
are costly or time-consuming. Bayesian optimization uses a probabilistic model to predict the function's
behavior and makes decisions based on these predictions to sample the most promising areas. It is particularly
effective for optimizing hyperparameters in machine learning models or any scenario where the objective
function does not have a simple analytical form and requires expensive evaluations.
• BayesianMaximization is similar to BayesianMinimization but focuses on finding the maximum value of
a function. Like its minimization counterpart, it uses Bayesian optimization strategies to intelligently explore
the function space, balancing the exploration of new areas with the exploitation of known good areas. This
function is particularly useful when dealing with complex optimization landscapes that are difficult to
navigate with traditional methods due to multiple local maxima or the expensive nature of function
evaluations.
These functions represent a powerful suite of tools in Mathematica for handling various types of data analysis,
predictive modeling, and optimization tasks, each equipped with sophisticated algorithms and easy-to-use interfaces
to cater to both novice users and expert analysts.
1. Predict
Predict[{in1->out1,in2->out2,…}]
generates a PredictorFunction[…] based on the example input-output pairs given.
Predict[{in1,in2,…}->{out1,out2,…}]
generates the same result.
Predict[training,input]
attempts to predict the output associated with input from the training examples given.
Predict["name",input]
uses the built-in predictor function represented by "name".
Predict[predictor,opts]
takes an existing predictor function and modifies it with the new options given.
402
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
2. GaussianProcess
GaussianProcess
Method for Predict.
Predict[data, Method->"GaussianProcess"]
Infers values by conditioning a Gaussian process on the training data.
3. BayesianMinimization/BayesianMaximization
BayesianMinimization [f,{conf1,conf2,…}]
gives an object representing the result of Bayesian minimization of the function f over the configurations confi.
BayesianMinimization[f,reg]
minimizes over the region represented by the region specification reg.
BayesianMinimization[f,sampler]
minimizes over configurations obtained by applying the function sampler.
BayesianMinimization [f,{conf1,conf2,…}->nsampler]
applies the function nsampler to successively generate configurations starting from the confi.
BayesianMaximization[f,{conf1,conf2,…}]
gives an object representing the result of Bayesian maximization over the function f over the configurations confi.
BayesianMaximization[f,reg]
maximizes over the region represented by the region specification reg.
403
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
BayesianMaximization[f,sampler]
maximizes over configurations obtained by applying the function sampler.
BayesianMaximization[f,{conf1,conf2,…}->nsampler]
applies the function nsampler to successively generate configurations starting from the confi.
Remarks:
• BayesianMinimization[…] returns a BayesianMinimizationObject[…] whose properties can be obtained
using BayesianMinimizationObject[…]["prop"].
• BayesianMinimizationObject[…][{prop1,prop2, …}] gives the list of properties {prop1,prop2,…}.
• BayesianMaximization[…] returns a BayesianMaximizationObject[…] whose properties can be obtained
using BayesianMaximizationObject[…]["prop"].
• BayesianMaximizationObject[…][{prop1,prop2,…}] gives the list of properties {prop1,prop2,…}.
• Configurations can be of any form accepted by Predict (single data element, list of data elements,
association of data elements, etc.) and of any type accepted by Predict (numerical, textual, sounds, images,
etc.).
Possible properties include:
"EvaluationHistory" configurations and values explored during minimization/maximization
"MinimumConfiguration"/ configuration found that minimizes/maximizes the result from f
"MaximumConfiguration"
"MinimumValue"/ estimated minimum/maximum value obtained from f
"MaximumValue"
"Method" method used for Bayesian maximization
"NextConfiguration" configuration to sample next if maximization were continued
"PredictorFunction" best prediction model found for the function f
"Properties" list of all available properties
(* Specify the training set as a list of rules between an input example and the
output value: *)
predictorWithSingleInput=Predict[{10->3.5,20->7.2,30->10.8,40->14.1,50->18.2}]
404
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Specify the training set as a list of rule between a list of inputs and a list
of outputs: *)
predictorWithInputList=Predict[{10,20,30,40,50}->{3.5,7.2,10.8,14.1,18.2}]
Output
Output 5.35
Output
Output 4.35
Output
Output 16.15
Output
Output 8.38009
(* Retrieve and display general information about the predictor, like the model
type, training points, etc: *)
Information[predictor]
(* Get the conditional distribution of the predicted value for a specific feature:
*)
predictedDistribution=predictor[2,"Distribution"]
(* Plot the probability density function (PDF) of the distribution for a given
feature value: *)
405
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Plot[
PDF[predictedDistribution,y],
{y,0,3},
PlotRange->Full,
ImageSize->250,
FrameLabel->{"Value","Probability Density"},
PlotLabel->"Probability Density Plot: \n Predicted Distribution at Feature Value
2"]
(* Calculate and plot the PDFs for a range of input values to visualize how
predictive uncertainty varies: *)
pdfs=Table[
PDF[predictor[i,"Distribution"],y],
{i,-2,5,0.1}
];
Plot[
pdfs,
{y,1,2},
PlotRange->Full,
ImageSize->300,
PlotStyle->{Thickness[0.001]},
FrameLabel->{"Value","Probability Density"},
PlotLabel->"Predicted Probability Density Functions\n for Various Input Values"]
(* Visualize the predicted mean, upper, and lower bounds of confidence intervals
across the input range and compare these predictions with the original training
data: *)
Show[
Plot[
{
(* Predicted mean: *)
predictor[x],
(* Upper bound of confidence interval: *)
predictor[x]+StandardDeviation[predictor[x,"Distribution"]],
(* Lower bound of confidence interval: *)
predictor[x]-StandardDeviation[predictor[x,"Distribution"]]
},
{x,-2,6},
PlotStyle->{Blue,{Opacity[0.3],Purple},{Opacity[0.3],Purple}},
(* Fill between the upper and lower confidence intervals: *)
Filling->{2->{3}},
FillingStyle->{Opacity[0.001],Blue},
Exclusions->False,
ImageSize->300,
PerformanceGoal->"Speed",
PlotLegends->{"Prediction","Confidence Interval"},
PlotLabel->"Gaussian Process Prediction with Confidence Intervals"
],
ListPlot[
(* Plot the actual training data points for comparison: *)
List@@@trainingData,
PlotStyle->{Red,PointSize[Large]},
PlotLegends->{"Data"}
]
]
406
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output NormalDistribution[1.51826,0.113466]
Output
Output
Output
407
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output 6.00389
Output NormalDistribution[6.00389,0.707892]
408
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
409
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
FrameTicksStyle->Thin,
FrameStyle->Thin,
ImageSize->250,
PerformanceGoal->"Speed"
],
(* Plot the original data points: *)
ListPlot[
Apply[List,dataset,{1}],
PlotMarkers->"OpenMarkers",
PlotLegends->{"Training Data"}
]
],{predictiveModel,{
{predictorSE,"SquaredExponential"},
{predictorPeriodic,"Periodic"},
{predictorRQ,"RationalQuadratic"},
{predictorMatern52,"Matern5/2"},
{predictorMatern32,"Matern3/2"}
}
}
]
Output
Output
Output
410
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output
(* Extract the optimal configuration (the x-value) from the optimization result.
This value represents the input at which the function is estimated to reach its
maximum within the defined interval: *)
optimalConfiguration=optimizationResult["MaximumConfiguration"]
(* Retrieve the highest function value achieved during the optimization. This value
corresponds to the maximum output of the function at the optimal configuration,
indicating the peak performance observed by the Bayesian optimization process: *)
optimalFunctionValue=optimizationResult["MaximumValue"]
411
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Epilog->{
Red,
PointSize[Large],
Point[{optimalConfiguration,optimalFunctionValue}]
},
PlotLegends->Placed[{"Function"},{0.8,0.8}],
PlotLabel->"Bayesian Optimization of\n f[x] = Sin[3x] Exp[-0.3x]",
ImageSize->250
]
Output
Output 0.474702
Output 0.865426
Output
412
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
PlotStyle->Thick,
Epilog->{
Red,
PointSize[Large],
Point[{optimalConfiguration,optimalFunctionValue}]
},
PlotLegends->Placed[{"Function"},{0.8,0.8}],
PlotLabel->"Bayesian Optimization of\n f[x] = Sin[3x] Exp[-0.3x]",
ImageSize->250
]
Output
Output 2.3
Output 0.290532
Output
Output
413
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output 8.75956
Output 0.0653677
Output
414
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
PlotLegends->Placed[{"Function"},{0.8,0.8}],
PlotLabel->"Bayesian Optimization of\n f[x] = Sin[3x] Exp[-0.3x]",
ImageSize->250,
PlotRange->Full
]
Output
Output 1.53078
Output -0.612163
Output
interval=Interval[{0,10}];
415
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output 0.474702
Output 0.865426
Output
Output 0.474702
Output 0.851354
416
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
probabilisticModel=bayesianOptimization["PredictorFunction"]
Output
Output {MaximumConfiguration,MaximumValue,EvaluationHistory,PredictorFunction,ObjectiveF
unction,Method,Properties,NextConfiguration}
Output
Output MaxExpectedImprovement
417
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output 0.527692
Output {0.513563,0.856509,MaxExpectedImprovement}
Output
(* Retrieve the list of configurations and function values explored during the
minimization: *)
evaluationHistory=bayesianMinimization["EvaluationHistory"]//Normal
418
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Show[
(* Visualize how well the function is modeled, particularly near the minimum: *)
Plot[
{objectiveFunction[x],probabilisticModel[{x}]},
{x,0,5},
PlotLegends->{"Function","Model"},
Frame->{True,True,False,False},
FrameLabel->{"Configuration","Function Value"},
Epilog->{
Red,
PointSize[Large],
Point[{minimumConfiguration,minimumValue}]
}
],
(* Plot the evaluation history: *)
ListPlot[
evaluationHistory,
PlotMarkers->"OpenMarkers",
PlotLegends->{"Evaluation History"}
],
PlotLabel->"Objective Function, Probabilistic Model\n and Evaluation History",
ImageSize->250
]
Output {MinimumConfiguration,MinimumValue,EvaluationHistory,PredictorFunction,ObjectiveF
unction,Method,Properties,NextConfiguration}
Output 1.56664
Output -0.61745
Output {<|Configuration->2.60982,Value->0.45692|>,<|Configuration->0.431117,Value-
>0.845077|>,<|Configuration->2.71878,Value->0.42229|>,<|Configuration-
>3.83488,Value->-0.276356|>,<|Configuration->4.70554,Value-
>0.243686|>,<|Configuration->3.71624,Value->-0.32412|>,<|Configuration-
>1.64323,Value->-0.596447|>,<|Configuration->1.40564,Value->-
0.577055|>,<|Configuration->1.74939,Value->-0.508755|>,<|Configuration-
>1.56664,Value->-0.624958|>,<|Configuration->1.38428,Value->-
0.559475|>,<|Configuration->4.84801,Value->0.214477|>}
Output {0.0582229,MaxExpectedImprovement}
419
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Unit 7.5
Automated Hyperparameter Tuning with Mathematica
In machine learning, hyperparameter optimization is crucial for enhancing model performance, and it can be
approached using methods like grid search, random search, and Bayesian optimization. Grid search evaluates every
possible combination of a predefined set of hyperparameters, ensuring a thorough exploration of the space but often
at a high computational cost. Random search, on the other hand, samples hyperparameters randomly from specified
distributions, providing a more efficient alternative that can sometimes yield better results in less time. Bayesian
optimization utilizes a probabilistic model to intelligently select hyperparameters based on past evaluations, aiming
to find optimal solutions faster by focusing on more promising areas of the hyperparameter space. Each method has
its advantages, and the choice depends on the specific constraints and goals of your project, such as computational
resources and the sensitivity of model performance to hyperparameters. For grid search, you can use nested loops to
iterate through combinations of hyperparameters. Similarly, for a random search, you can generate random samples
of hyperparameters using Mathematica's random number generation functions like RandomChoice. Bayesian
optimization, facilitated by functions like BayesianMinimization/BayesianMaximization in Mathematica,
employs probabilistic models to sequentially select hyperparameters, updating the model based on observed results to
iteratively explore the parameter space efficiently.
dataFunction[x_]:=Exp[-x^2];
noiseLevel=0.15;
420
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
];
(* Set up arrays for hyperparameter tuning: learning rates, neuron counts in layers
and optemization method: *)
learningRates={0.001,0.05,0.1};
neuronCounts={10,30,40};
optemizationmethod={"ADAM","SGD","RMSProp"};
{learningRate,neurons,method,validationMSE,validationRS,trainedNet}
],
(* Grid of hyperparameters : *)
{learningRate,learningRates},
{neurons,neuronCounts},
{method,optemizationmethod}
];
(* Flatten the results and sort by MSE and RS to find the best parameters: *)
sortedResultsByMSE=SortBy[Flatten[results,2],#[[4]]&];
sortedResultsByRS=SortBy[Flatten[results,2],#[[5]]&];
421
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Visualize the best model's predictions along with the actual test data: *)
plotModelByMSE=Plot[
bestModelByMSE[x],
{x,-3,3},
PlotStyle->{Purple,Thick},
PlotLegends->{"Model"}
];
plotModelByRS=Plot[
bestModelByRS[x],
{x,-3,3},
PlotStyle->{Purple,Thick},
PlotLegends->{"Model"}
];
plottestData=ListPlot[
List@@@testData,
PlotStyle->Orange,
PlotLegends->{"Test Data"}
];
422
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output
423
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* note that in this example, we will generate new data by using RandomVariate.
Therefore, we cannot accurately compare the results of random search and grid
search. Our objective is to elucidate the workings of each search method: *)
424
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
trainingData,
All,
ValidationSet->validationData,
TrainingProgressMeasurements->{"MeanSquare","RSquared"},
LossFunction->MeanSquaredLossLayer[],
BatchSize->64,
LearningRate->learningRate,
Method->method,
TimeGoal->5
];
{learningRate,neurons,method,validationMSE,validationRS,trainedNet}
],
{numTrials}
];
(* Flatten the results and sort by MSE and RS to find the best parameters: *)
sortedResultsByMSE=SortBy[results,#[[4]]&];
sortedResultsByRS=SortBy[results,#[[5]]&];
(* Visualize the best model's predictions along with the actual test data: *)
plotModelByMSE=Plot[
bestModelByMSE[x],
{x,-3,3},
PlotStyle->{Purple,Thick},
PlotLegends->{"Model"}
];
plotModelByRS=Plot[
bestModelByRS[x],
{x,-3,3},
PlotStyle->{Purple,Thick},
PlotLegends->{"Model"}
];
plottestData=ListPlot[
List@@@testData,
PlotStyle->Orange,
PlotLegends->{"Test Data"}
];
425
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
426
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
Output
(* Set the standard deviation of the Gaussian noise to be added to the data,
simulating measurement errors or intrinsic variability: *)
noiseLevel=0.15;
(* Generate validation data similar to the training data but with less frequent
sampling (step of 0.1): *)
validationData=Table[
x->dataFunction[x]+RandomVariate[NormalDistribution[0,noiseLevel]],
{x,-3,3,0.1}
];
427
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
{x,-3,3,0.1}
];
(* Define the objective function that will be minimized during the hyperparameter
optimization process. This function constructs a neural network, trains it with a
specific learning rate, and evaluates its performance using the mean squared error
on the validation set: *)
objectiveFunction[learningRate_]:=Module[
{net,trainedNet,validationMSE},
net=NetChain[
{
LinearLayer[50],Tanh,
LinearLayer[30],Tanh,
LinearLayer[1]
}
];
trainedNet=NetTrain[
net,
trainingData,
All,
ValidationSet->validationData,
TrainingProgressMeasurements->{"MeanSquare"},
LossFunction->MeanSquaredLossLayer[],
BatchSize->64,
(* Set the learning rate as specified by the optimization function: *)
LearningRate->learningRate,
Method->"ADAM",
MaxTrainingRounds->5
];
(* Extract the mean squared error from validation measurements: *)
validationMSE=Values[trainedNet["ValidationMeasurements"]][[2]];
validationMSE
];
(* Extract the optimal learning rate found by the optimization process and the
corresponding lowest MSE achieved: *)
bestParameters=optimizationResult["MinimumConfiguration"]
bestMSE=optimizationResult["MinimumValue"]
(* Retrieve the complete history of learning rates and MSEs evaluated during the
optimization, which can be useful for analysis: *)
evaluationHistory=optimizationResult["EvaluationHistory"]
(* Train the final model using the best learning rate determined through
optimization. This model will be evaluated against the test data: *)
finalModel=NetTrain[
NetChain[
{
LinearLayer[50],Tanh,
LinearLayer[30],Tanh,
LinearLayer[1]
}
428
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
],
trainingData,
All,
LossFunction->MeanSquaredLossLayer[],
BatchSize->64,
LearningRate->bestParameters,
Method->"ADAM",
MaxTrainingRounds->5
];
(* Extract the final trained neural network for use in plotting predictions: *)
finalModeltoplot=finalModel["TrainedNet"];
(* Plot the predictions from the final trained model across the range of input data
to visualize how well it has learned to approximate the underlying function: *)
plotModel=Plot[
finalModeltoplot[x],
{x,-3,3},
PlotStyle->{Purple,Thick},
PlotLegends->{"Model"}
];
(* Create a scatter plot of the actual test data points to compare against the
model's predictions. This helps visually assess the accuracy and fit of the model.*)
plottestData=ListPlot[
List@@@testData,
PlotStyle->Orange,
PlotLegends->{"Test Data"}
];
(* Combine the plot of the model's predictions with the scatter plot of the test
data to provide a comprehensive visualization of model performance: *)
Show[plotModel,plottestData,ImageSize->250]
Output 0.0114483
Output 0.02434
Output
429
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
Output
(* Generate training data with fine granularity by adding Gaussian noise to simulate
measurement errors: *)
trainingData=Table[
x->dataFunction[x]+RandomVariate[NormalDistribution[0,noiseLevel]],
{x,-3,3,0.01}
];
(* Define the objective function for Bayesian optimization, which trains a neural
network and computes the MSE on the validation set: *)
objectiveFunction[{learningRate_,neurons1_,neurons2_,method_}]:=Module[
{net,trainedNet,validationMSE},
net=NetChain[
{
LinearLayer[neurons1],Tanh,
LinearLayer[neurons2],Tanh,
LinearLayer[1]
}
];
430
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
trainedNet=NetTrain[
net,
trainingData,
All,
ValidationSet->validationData,
TrainingProgressMeasurements->{"MeanSquare"},
LossFunction->MeanSquaredLossLayer[],
BatchSize->64,
LearningRate->learningRate,
Method->method,
MaxTrainingRounds->10
];
(* Extract the MSE from validation measurements: *)
validationMSE=Values[trainedNet["ValidationMeasurements"]][[2]];
validationMSE
];
(* Define ranges and options for hyperparameters: learning rates, n umber of neurons
in each layer, and optimizer methods: *)
learningRates={0.00001,0.0001,0.001,0.01,0.1};
numberOfNeuronsLayer1={30,40};
numberOfNeuronsLayer2={5,10,30};
optimizers={"ADAM","SGD","RMSProp"};
(* Store the initial evaluation history from the first round of optimization: *)
evaluationHistory1=optimizationResult1["EvaluationHistory"]
431
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
(* Store the final evaluation history and extract the best hyperparameters and
their corresponding MSE: *)
evaluationHistory2=optimizationResult2["EvaluationHistory"]
bestParameters=optimizationResult2["MinimumConfiguration"]
bestMSE=optimizationResult2["MinimumValue"]
(* Train the final model using the optimal parameters found from Bayesian
optimization for final evaluation: *)
finalModel=NetTrain[
NetChain[
{
LinearLayer[bestParameters[[2]]],Tanh,
LinearLayer[bestParameters[[3]]],Tanh,
LinearLayer[1]
}
],
trainingData,
All,
LossFunction->MeanSquaredLossLayer[],
BatchSize->64,
LearningRate->bestParameters[[1]],
Method->bestParameters[[4]],
MaxTrainingRounds->10
];
(* Extract the final trained neural network for plotting its predictions: *)
finalModeltoplot=finalModel["TrainedNet"];
(* Visualization: *)
(* Plot the predictions from the final trained model across the range of input data
to visualize how well it has learned to approximate the underlying function: *)
plotModel=Plot[
finalModeltoplot[x],
{x,-3,3},
PlotStyle->{Purple,Thick},
PlotLegends->{"Model"}
];
(* Create a scatter plot of the actual test data points to compare against the
model's predictions. This helps visually assess the accuracy and fit of the model:
*)
plottestData=ListPlot[
List@@@testData,
PlotStyle->Orange,
PlotLegends->{"Test Data"}
];
(* Combine the plot of the model's predictions with the scatter plot of the test
data to provide a comprehensive visualization of model performance: *)
Show[plotModel,plottestData,ImageSize->250]
Output {{0.1,40,30,ADAM},{0.00001,30,30,SGD},{0.01,40,10,ADAM},{0.00001,30,5,ADAM},{0.00
1,30,5,SGD},{0.0001,40,10,SGD},{0.1,40,5,ADAM},{0.1,30,30,RMSProp},{0.0001,40,30,
RMSProp},{0.1,40,10,RMSProp},{0.1,40,10,RMSProp},{0.0001,40,10,SGD},{0.001,40,30,
RMSProp},{0.1,40,10,ADAM},{0.001,40,5,RMSProp},{0.0001,30,30,ADAM},{0.1,40,30,RMS
Prop},{0.001,30,30,ADAM},{0.1,40,5,ADAM},{0.0001,40,30,SGD},{0.1,30,5,SGD},{0.001
,30,30,ADAM},{0.001,30,5,SGD},{0.0001,30,10,ADAM},{0.01,30,10,ADAM},{0.00001,30,1
0,ADAM},{0.00001,40,30,SGD},{0.0001,30,10,SGD},{0.01,30,5,SGD},{0.0001,40,5,RMSPr
432
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
op},{0.001,40,30,ADAM},{0.001,30,30,SGD},{0.1,40,10,ADAM},{0.00001,30,30,ADAM},{0
.01,40,5,ADAM},{0.00001,30,10,SGD},{0.00001,40,5,SGD},{0.001,30,10,RMSProp},{0.00
01,30,10,SGD},{0.01,30,5,RMSProp},{0.0001,30,10,SGD},{0.01,30,30,RMSProp},{0.0000
1,30,30,SGD},{0.0001,40,30,SGD},{0.1,30,30,SGD},{0.001,40,10,SGD},{0.1,40,10,ADAM
},{0.01,40,5,RMSProp},{0.01,40,10,ADAM},{0.0001,40,30,RMSProp}}
Output
Output
Output {0.01,40,5,ADAM}
Output 0.0250422
Output
433
CHAPTER 7 STRATEGIES FOR GENERALIZATION AND HYPER-PARAMETER TUNING
434
CHAPTER 8 REGULARIZATION TECHNIQUES
CHAPTER 8
REGULARIZATION TECHNIQUES
Remark:
This chapter provides a Mathematica implementation of the concepts and ideas presented in Chapter 7, [1], of the
book titled Artificial Neural Network and Deep Learning: Fundamentals and Theory. We strongly recommend that
you begin with the theoretical chapter to build a solid foundation before exploring the corresponding practical
implementation.
In machine learning, particularly in the field of deep learning, the complexity of models often leads to a significant
challenge: overfitting. Overfitting occurs when a model learns the detail and noise in the training data to an extent that
it negatively impacts the performance of the model on new data. The essence of regularization is to constrain our
model in such a way that it avoids overfitting and thus performs better on unseen datasets. This chapter offers a
comprehensive exploration of the strategies used to improve the generalization ability of neural networks (NNs). By
introducing regularization techniques into the training process, we aim to develop models that are not only accurate
on the training data but also robust and adaptable to new, unseen data. This chapter will cover three principal
regularization techniques: penalty-based regularization, early stopping, and ensemble methods (dropout), each
addressing overfitting in a unique way.
Penalty-Based Regularization:
Penalty-Based Regularization involves modifying the loss function by adding a penalty term to it. This term penalizes
certain values of model parameters to discourage complexity:
• 𝐿1 regularization (Lasso) promotes sparsity by adding a penalty equivalent to the absolute value of the
coefficients, which can reduce the number of features in the model [127-138].
• 𝐿2 regularization (Ridge) adds a penalty equivalent to the square of the magnitude of the coefficients,
encouraging the model parameters to be small and distributing the error among them.
• Elastic net combines both 𝐿1 and 𝐿2 penalties and is useful when there are correlations among features.
Early Stopping:
Early Stopping is a different kind of regularization technique that does not modify the loss function but rather alters
the training process itself. Early stopping involves monitoring the model's performance on a validation set and
stopping the training as soon as the performance starts to degrade, despite improvements on the training set. This
method not only helps in preventing overfitting but also saves computational resources by reducing unnecessary
training iterations.
Ensemble methods [139,140], with focus on dropout, is a powerful regularization technique particularly popular in
training deep NNs. Unlike penalty-based methods, dropout works by randomly deactivating a subset of neurons in
each training iteration. This randomness helps to break up situations where network layers co-adapt to correct mistakes
from prior layers, thus making the model more capable of generalizing well.
By integrating these regularization techniques, machine learning practitioners can enhance model performance
significantly. This chapter will equip you with the knowledge to understand these methods conceptually, ensuring that
your NNs are not just powerful, but also robust and efficient.
435
CHAPTER 8 REGULARIZATION TECHNIQUES
This chapter delves into three essential regularization techniques implemented in Mathematica:
L2Regularization, TrainingStoppingCriterion, and DropoutLayer. Each method addresses overfitting from a
unique perspective, offering a robust toolkit for building and fine-tuning machine learning models.
In Mathematica, 𝐿2 -regularization can be applied by specifying the L2Regularization suboption within the
Method option of the NetTrain function. This integration allows users to seamlessly incorporate 𝐿2 regularization into
the training process, enhancing the model's ability to generalize.
An effective way to prevent overfitting is to stop the training process at the right moment before the model begins
to overfit the training data. The TrainingStoppingCriterion option in NetTrain provides a systematic approach to
determine when to halt training. This criterion can be based on various metrics, such as validation loss or accuracy,
ensuring that the training process concludes when the model reaches optimal performance on validation data.
Implementing a training stopping criterion helps in maintaining the model's generalization capability by avoiding
excessive training.
In Mathematica, the DropoutLayer can be integrated into NN architectures, providing an easy-to-use mechanism
for applying dropout regularization.
436
CHAPTER 8 REGULARIZATION TECHNIQUES
Unit 8.1
𝑳𝟐 Regularization
In Mathematica, during the training of neural networks with the NetTrain function, you can apply ℓ2 regularization
by specifying L2Regularization as a suboption of the Method option. This regularization helps prevent overfitting
by penalizing larger weights in the model's loss function.
The suboption "L2Regularization" can be given in the following forms:
r use the value r for all weights in the net
{lspec1->r1,lspec2->r2,…} use the value ri for the specific part lspeci of the net
(* Define a neural network with two hidden layers of 150 units each and Tanh
activation function: *)
neuralNetwork=NetChain[
{
150,Tanh,
150,Tanh,
1
}
];
(* Train the neural network on the synthetic data for a maximum of 5000 rounds:
*)
trainingResults=NetTrain[
neuralNetwork,
syntheticData,
All,
MaxTrainingRounds->5000
]
437
CHAPTER 8 REGULARIZATION TECHNIQUES
(* Plot the prediction of the overfitted network against the original data: *)
overfitPlot=Show[
Plot[
overfittedNetwork[x],
{x,-3,3},
PlotLegends->{"Overfitted Model"}
],
dataPlot,
PlotLabel->"Overfitted Model vs. Synthetic Data",
ImageSize->250
]
(* Generate test data with the same distribution as the training data: *)
testData=Table[
x->Exp[-x^2]+RandomVariate[NormalDistribution[0,0.15]],
{x,-3,3,0.2}
];
testXValues=Keys[testData];
testYValues=Values[testData];
(* Define a function to calculate the mean squared loss on the test data: *)
calculateMeanTestLoss[network_]:=SquaredEuclideanDistance[network[testXValues],te
stYValues]/Length[testXValues];
(* Train the neural network with L2 regularization to prevent overfitting: *)
regularizedTrainingResults=NetTrain[
neuralNetwork,
syntheticData,
All,
Method->{"SGD","L2Regularization"->0.01},
MaxTrainingRounds->5000
]
(* Retrieve the trained network with L2 regularization: *)
regularizedNetwork=regularizedTrainingResults["TrainedNet"];
(* Plot the prediction of the L2 regularized network against the original data: *)
regularizedPlot=Show[
Plot[
regularizedNetwork[x],
{x,-3,3},
PlotLegends->{"Regularized Model"}
],
dataPlot,
PlotLabel->"Regularized Model vs. Synthetic Data",
ImageSize->250
]
(* Calculate and display the mean test loss for the L2 regularized network: *)
Print[
"The mean test loss for the L2 regularized network is: ",
calculateMeanTestLoss[regularizedNetwork]
];
(* Calculate and display the mean test loss for the overfitted network: *)
Print[
"The mean test loss for the overfitted network is: ",
calculateMeanTestLoss[overfittedNetwork]
438
CHAPTER 8 REGULARIZATION TECHNIQUES
];
Output
Output
Output
439
CHAPTER 8 REGULARIZATION TECHNIQUES
Output
Output The mean test loss for the L2 regularized network is: 0.0244639
Output The mean test loss for the overfitted network is: 0.0343867
(* Create a list of neural networks with the same architecture for each
regularization rate: *)
neuralNetworks=Table[
NetChain[
{
(* First hidden layer with 100 units and Tanh activation: *)
100,Tanh,
(* Second hidden layer with 100 units and Tanh activation: *)
100,Tanh,
(*Output layer*)
1
}
],
{rate,regularizationRates}
];
(* Train each neural network on the synthetic data with the corresponding L2
regularization rate: *)
trainedNetworks=Table[
NetTrain[
(*Neural network to be trained*)
neuralNetworks[[i]],
(*Training data*)
440
CHAPTER 8 REGULARIZATION TECHNIQUES
syntheticData,
(*Maximum number of training rounds*)
MaxTrainingRounds->5000,
(*Training method with L2 regularization*)
Method->{"SGD","L2Regularization"->regularizationRates[[i]]}
],
{i,1,Length[regularizationRates]}
];
(* Plot the predictions of the trained networks and the original data: *)
Show[
Plot[
(*Predictions of the trained networks*)
{trainedNetworks[[1]][x],trainedNetworks[[2]][x],trainedNetworks[[3]][x]},
{x,-3,3},
ImageSize->300,
PlotRange->All,
(*Legends for the different regularization rates*)
PlotLegends->{"L2 Rate 0.1","L2 Rate 0.01","L2 Rate 0.000001"},
PlotLabel->"Comparison of Different L2 Regularization Rates"
],
ListPlot[
(* Plot the original synthetic data: *)
List@@@syntheticData,
PlotStyle->{Red,PointSize[0.01]},
PlotLegends->{"Synthetic Data"}
]
]
Output
441
CHAPTER 8 REGULARIZATION TECHNIQUES
Unit 8.2
TrainingStoppingCriterion
TrainingStoppingCriterion
is an option for NetTrain that specifies a criterion for stopping training early in order to prevent overfitting.
Remarks:
• TrainingStoppingCriterion->Automatic is equivalent to TrainingStoppingCriterion->"Loss".
• If the validation set is present, the stopping criterion is checked whenever the validation loss and metrics are
calculated (once per round by default); otherwise, the stopping criterion is checked once per round.
• TrainingStoppingCriterion has a number of suboptions that can be specified using the <|"Criterion"-
>"measurement",opt1->val1,opt2->val2,…|> syntax.
• Setting TrainingStoppingCriterion-> <|"Criterion"->"measurement","Patience"->n|> specifies
that training should be stopped if an improvement in measurement is not seen for n rounds in a row. The
default value for n is 0.
• Setting TrainingStoppingCriterion-> <|"Criterion"->"measurement","InitialPatience"->n |>
specifies that the stopping criterion is only checked for the first time after n rounds. The default value for n
is 0.
• Setting TrainingStoppingCriterion-> <|"Criterion"->"measurement", "Improvement"->v|>
specifies the minimum change in measurement that is considered an improvement. Possible values for
improvement are:
442
CHAPTER 8 REGULARIZATION TECHNIQUES
x->Exp[-x^2]+RandomVariate[NormalDistribution[0,0.15]],
{x,-3,3,0.1}
];
Show[
Plot[
443
CHAPTER 8 REGULARIZATION TECHNIQUES
earlyStoppedNetwork[x],
{x,-3,3},
ImageSize->250
],
ListPlot[
List@@@trainingData,
PlotStyle->Purple
]
]
fineGrainedStoppingResultsRelative=NetTrain[
initialNetwork,
trainingData,
"LossPlot",
ValidationSet->validationData,
TrainingStoppingCriterion-><|"Criterion"->"Loss","RelativeChange"-
>0.01,"InitialPatience"->200|>
]
Output
444
CHAPTER 8 REGULARIZATION TECHNIQUES
Output
Output
Output
Output
445
CHAPTER 8 REGULARIZATION TECHNIQUES
Output
Output
Output
446
CHAPTER 8 REGULARIZATION TECHNIQUES
(* Assign labels based on whether the point's distance from the origin is less
than 0.5: *)
trainlabels=Thread[Map[Norm,trainpoints]<0.5];
(* Assign labels using the same criteria as for the training set: *)
validationLabels=Thread[Map[Norm,validationPoints]<0.5];
(* Visualize the synthetic training set with different colors for each class: *)
ListPlot[
{
Pick[trainpoints,trainlabels,True],
Pick[trainpoints,trainlabels,False]
},
AspectRatio->1,
ImageSize->250,
PlotStyle->PointSize[Medium],
FrameLabel->{"X","Y","Synthetic Training Set"},
PlotLegends->{"Class 1","Class 2"}
]
(* Define a neural network with two linear layers and activation functions: *)
net=NetChain[
{
LinearLayer[20],ElementwiseLayer[Tanh],
LinearLayer[],ElementwiseLayer[LogisticSigmoid]},
"Output"->NetDecoder["Boolean"]
];
(* Train the neural network on the training data with specified metrics and
validation: *)
netTrainResults=NetTrain[
net,
trainingData,
All,
ValidationSet->validationData,
TrainingProgressMeasurements->{"Recall","Accuracy","ConfusionMatrixPlot"},
(* Use TrainingStoppingCriterion to stop training when the validation recall
has stopped increasing for 20 iterations after Initial Patience 150 rounds: *)
TrainingStoppingCriterion-><|"Criterion"->"Recall","InitialPatience"-
>150,"Patience"->20|>
];
447
CHAPTER 8 REGULARIZATION TECHNIQUES
ContourPlot[
trainedNet[{x,y},None],
{x,-1,1},
{y,-1,1},
ContourStyle->{White},
ClippingStyle->Automatic,
ColorFunction->"BlueGreenYellow",
PlotLegends->Automatic,
LabelStyle->Directive[Black,10],
ImageSize->250,
PlotLabel->"Trained Nonlinear Classifier Decision Boundary"]
(* Display additional training plots like loss, Recall, Accuracy, and confusion
matrix: *)
lossPlot=netTrainResults["FinalPlots"][[1]]
recallPlot=netTrainResults["FinalPlots"][[2]]
accuracyPlot=netTrainResults["FinalPlots"][[3]]
confusionmatrixPlot=netTrainResults["FinalPlots"][[4]]
Output
Output <|Loss->0.140352,Recall->0.875,Accuracy->0.96,ConfusionMatrixPlot->
448
CHAPTER 8 REGULARIZATION TECHNIQUES
Output
Output
Output
Output
449
CHAPTER 8 REGULARIZATION TECHNIQUES
Output
(* Assign labels based on whether the point's distance from the origin is less
than 0.5: *)
450
CHAPTER 8 REGULARIZATION TECHNIQUES
trainlabels=Thread[Map[Norm,trainpoints]<0.5];
(* Assign labels using the same criteria as for the training set: *)
validationLabels=Thread[Map[Norm,validationPoints]<0.5];
(* Define a neural network with two linear layers and activation functions: *)
net=NetChain[
{
LinearLayer[20],ElementwiseLayer[Tanh],
LinearLayer[],ElementwiseLayer[LogisticSigmoid]},
"Output"->NetDecoder["Boolean"]
];
(* Train the neural network on the training data with specified metrics and
validation: *)
netTrainResults=NetTrain[
net,
trainingData,
All,
ValidationSet->validationData,
TrainingProgressMeasurements->{"Recall","Accuracy","ConfusionMatrixPlot"},
(* Stop training if the validation loss is less than 0.3 for more than 10 rounds
in a row: *)
TrainingStoppingCriterion-><|"Criterion"-
>Function[#ValidationLoss<0.3],"Patience"->10|>
]
451
CHAPTER 8 REGULARIZATION TECHNIQUES
Output
Output <|Loss->0.269947,Recall->0.706767,Accuracy->0.922,ConfusionMatrixPlot->
452
CHAPTER 8 REGULARIZATION TECHNIQUES
Output
(* Stop training if the L1 norm of the first layer activations does not increase:
*)
(* Assign labels based on whether the point's distance from the origin is less than
0.5: *)
trainlabels=Thread[Map[Norm,trainpoints]<0.5];
(* Assign labels using the same criteria as for the training set: *)
validationLabels=Thread[Map[Norm,validationPoints]<0.5];
(* Define a neural network with two linear layers and activation functions: *)
net=NetChain[
{
LinearLayer[20],ElementwiseLayer[Tanh],
LinearLayer[],ElementwiseLayer[LogisticSigmoid]},
"Output"->NetDecoder["Boolean"]
];
(* Train the neural network on the training data with specified metrics and
validation: *)
netTrainResults=NetTrain[
net,
453
CHAPTER 8 REGULARIZATION TECHNIQUES
trainingData,
All,
ValidationSet->validationData,
(* Stop training if the L1 norm of the first layer activations does not
increase: *)
TrainingProgressMeasurements-><|
"Measurement"->NetPort[{"1","Output"}],
"Aggregation"->"L1Norm",
"Direction"->"Increasing"
|>,
TrainingStoppingCriterion-><|"Criterion"->"1/Output","Patience"->9|>
]
Output
454
CHAPTER 8 REGULARIZATION TECHNIQUES
Output <|Loss->0.570178,1/Output->7.82789|>
Output
455
CHAPTER 8 REGULARIZATION TECHNIQUES
Unit 8.3
DropoutLayer
DropoutLayer[]
represents a net layer that sets its input elements to zero with probability 0.5 during training.
DropoutLayer[p]
sets its input elements to zero with probability p during training.
(* Apply the dropout layer to an input vector {1,2,3,4,5} in evaluation mode (which
remains unchanged): *)
drop[{1,2,3,4,5}]
(* Apply the dropout layer to the same input vector in training mode: *)
(* In training mode, the dropout layer randomly drops (sets to zero) some of the
input units: *)
drop[{1,2,3,4,5},NetEvaluationMode->"Train"]
Output
Output {1.,2.,3.,4.,5.}
Output {2.,0.,0.,8.,10.}
456
CHAPTER 8 REGULARIZATION TECHNIQUES
(* Apply the dropout layer to the same input vector in training mode: *)
drop[{1,2,3,4,5,6,7,8,9,10},NetEvaluationMode->"Train"]
Output
Output {1.,2.,3.,4.,5.,6.,7.,8.,9.,10.}
Output {5.,0.,0.,0.,0.,0.,0.,0.,0.,50.}
Output
Output {1.6656,2.552,-0.779194,4.32481,5.21122,6.09762,-0.779194}
457
CHAPTER 8 REGULARIZATION TECHNIQUES
PlotStyle->Red,
PlotLabel->"Synthetic Data"
];
(* Define a neural network with two hidden layers of 150 units each and Tanh
activation functions: *)
basicNeuralNetwork=NetChain[
{
150,Tanh,
150,Tanh,
1
}
];
(* Train the neural network on the synthetic data for a maximum of 10000 rounds:
*)
trainingResultsBasic=NetTrain[
basicNeuralNetwork,
syntheticData,
All,
MaxTrainingRounds->10000
]
(* Plot the predictions of the overfitted network against the original data: *)
Show[
Plot[
overfittedNetwork[x],
{x,-3,3},
ImageSize->250,
PlotLabel->"Overfitted Network Predictions"
],
dataPlot
]
(* Generate test data with the same distribution as the training data: *)
testData=Table[
x->Exp[-x^2]+RandomVariate[NormalDistribution[0,0.15]],
{x,-3,3,0.1}
];
testInputs=Keys[testData];
testOutputs=Values[testData];
(* Train the dropout neural network on the synthetic data for a maximum of 10000
rounds: *)
trainingResultsDropout=NetTrain[
dropoutNeuralNetwork,
syntheticData,
All,
458
CHAPTER 8 REGULARIZATION TECHNIQUES
MaxTrainingRounds->10000
]
(* Plot the predictions of the trained dropout network against the original data:
*)
Show[
Plot[
trainedDropoutNetwork[x],
{x,-3,3},
PlotLabel->"Dropout Network Predictions",
ImageSize->250
],
dataPlot
]
(* Create a function to measure the mean squared error on the test set: *)
meanTestLoss[network_]:=SquaredEuclideanDistance[network[testInputs],testOutputs]
/Length[testInputs];
(* Calculate and display the mean test loss for the dropout network: *)
meanTestLossDropout=meanTestLoss[trainedDropoutNetwork];
(* Calculate and display the mean test loss for the overfitted network: *)
meanTestLossOverfit=meanTestLoss[overfittedNetwork];
{meanTestLossDropout,meanTestLossOverfit}
Output
459
CHAPTER 8 REGULARIZATION TECHNIQUES
Output
Output
Output
Output {0.0277502,0.0356406}
460
CHAPTER 8 REGULARIZATION TECHNIQUES
of how different dropout rates influence the networks' ability to generalize and
fit the data, highlighting the effect of dropout as a regularization technique: *)
(* Create a list of neural networks with the same architecture but different dropout
rates: *)
neuralNetworks=Table[
NetChain[
{
(* First hidden layer with 100 units and Tanh activation: *)
100,Tanh,
(* Dropout layer with the specified rate: *)
DropoutLayer[rate],
(* Second hidden layer with 100 units and Tanh activation: *)
100,Tanh,
(*Output layer*)
1
}
],
{rate,dropoutRates}
];
(* Train each neural network on the synthetic data with the corresponding dropout
rate: *)
trainedNetworks=Table[
NetTrain[
network,
syntheticData,
LearningRate->0.01,
MaxTrainingRounds->5000
],
{network,neuralNetworks}
];
461
CHAPTER 8 REGULARIZATION TECHNIQUES
]
]
Output
(* Create a list of neural networks with the same architecture but different dropout
rates: *)
neuralNetworks=Table[
NetChain[
{(* First hidden layer with 100 units and Tanh activation: *)
100,Tanh,
(* Dropout layer with the specified rate: *)
DropoutLayer[rate],
(* Second hidden layer with 100 units and Tanh activation: *)
100,Tanh,
(* Output layer: *)
1
}
],
{rate,dropoutRates}
];
(* Train each neural network on the synthetic data with the corresponding dropout
rate: *)
462
CHAPTER 8 REGULARIZATION TECHNIQUES
trainedNetworks=Table[
NetTrain[
network,
syntheticData,
LearningRate->0.01,
MaxTrainingRounds->5000,
Method->{"SGD","L2Regularization"->0.01}
],
{network,neuralNetworks}
];
Output
463
CHAPTER 8 REGULARIZATION TECHNIQUES
464
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
CHAPTER 9
ADVANCED ACTIVATION FUNCTIONS
Remark:
This chapter provides a Mathematica implementation of the concepts and ideas presented in Chapter 8, [1], of the
book titled Artificial Neural Network and Deep Learning: Fundamentals and Theory. We strongly recommend that
you begin with the theoretical chapter to build a solid foundation before exploring the corresponding practical
implementation. This chapter also serves as a summary of the article titled Deep Learning Activation Functions:
Fixed-Shape, Parametric, Adaptive, Stochastic, Miscellaneous, Non-Standard, Ensemble. For more details about
activation functions, please refer to Ref [24]."
The activation functions (AFs) play a very crucial role in Neural Networks (NNs) by learning the abstract features
through non-linear transformations. Some common properties of the AFs are as follows: a) it should add the non-
linear curvature in the optimization landscape to improve the training convergence of the network; b) it should not
increase the computational complexity of the model extensively; c) it should not hamper the gradient flow during
training. Several AFs have been explored in recent years for deep learning to achieve the above-mentioned properties.
For a more comprehensive background, we refer to [24] and the references cited therein.
In the present work, we categorized the AFs into six distinct groups: sigmoid-based, ReLU-based, ELU-based,
miscellaneous, non-standard, and ensemble AFs.
Sigmoid-Based AFs: In order to introduce non-linearity into the NNs, the Logistic Sigmoid, and Tanh AFs have
been used in the early days. The firing of biological neurons was the motivation for using the Logistic Sigmoid and
Tanh AFs with artificial neurons. The Logistic Sigmoid and Tanh AFs majorly suffer from vanishing gradients.
Several improvements have been proposed based on the Logistic Sigmoid AF. The most common Sigmoid-
based/related functions are Tanh, HardSigmoid, and HardTanh, Penalized Tanh, Soft-Root-Sign, and Sigmoid-
Weighted Linear.
ReLU-Based AFs: The saturated output and increased complexity are the key limitations of the above-mentioned
Logistic Sigmoid-based AFs. The ReLU has become the state-of-the-art AF due to its simplicity and improved
performance. Various variants of ReLU have been investigated by tackling its drawbacks, such as non-utilization of
negative values, limited non-linearity, and unbounded output. The most common ReLU-based/related functions are:
Leaky Rectified Linear Unit, Parametric ReLU, Randomized ReLU, Random Translation ReLU, Elastic ReLU, Elastic
Parametric ReLU, Linearized Sigmoidal Activation, Rectified Linear Tanh, Shifted ReLU, Displaced ReLU and
Multi-bin Trainable Linear Unit.
ELU-Based AFs: The major problem faced by the Logistic Sigmoid-based AFs is with its saturated output for large
positive and negative input. Similarly, the major problem with ReLU-based AFs is the under-utilization of negative
values leading to a vanishing gradient. In order to cope up with these limitations the ELU-based AFs have been used
in the literature. The ELU-based AF utilizes the negative values with the help of the exponential function. Several
AFs have been introduced in the literature as ELU variants. The most common ELU-based/related functions are Scaled
ELU, Parametric ELU, Rectified Exponential Unit, Parametric Rectified Exponential Unit, and Elastic ELU.
Non-Standard AFs: Non-standard AFs include those that combine multiple standard functions or operate on
different principles. The common non-standard AFs are Maxout and Softmax.
465
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Miscellaneous AFs: Such as Swish-based/related AFs (Swish, E-Swish, HardSwish), SoftPlus-based/related AFs
(SoftPlus, SoftPlus Linear Unit, Mish), Probabilistic AF (Gaussian Error Linear Unit, and Symmetrical Gaussian Error
Linear Unit).
Combining AFs: Most of the Sigmoid, Tanh, ReLU, and ELU-based AFs are designed manually which might not
be able to exploit the data complexity. Combining AFs are the recent trends. The most common AF are Mixed, Gated,
and Hierarchical AFs, Adaptive Piecewise Linear Units, Mexican ReLU, Look-up Table Unit, and Bi-Modal
Derivative Sigmoidal AFs. Unlike traditional AFs such as ReLU, Sigmoid, or ELU, which have fixed functional
forms, adaptive AFs learn their parameters from the data, allowing the network to adapt more flexibly to different
tasks.
In this chapter, we embark on an in-depth exploration of AFs and custom layers within NNs. The primary goal is
to provide a comprehensive understanding of how these functions influence the behavior of NNs. We will achieve this
through interactive simulations, detailed comparisons, and practical implementations of custom layers. This chapter
is structured into three units, each focusing on a specific aspect of AFs and custom layers.
In this unit, we explore the behavior of AFs by creating interactive Manipulate visualizations. These visualizations
allow us to dynamically change the parameters and observe how they affect the AFs. By adjusting parameters such as
slope, threshold, and others, we gain deeper insights into how each AF transforms its input and impacts the overall
behavior of a NN. This hands-on approach helps to solidify our understanding of the role of AFs in NNs. Through
these interactive simulations, you will develop an intuitive grasp of the mathematical underpinnings and practical
implications of various AFs. By experimenting with different parameter settings, you will see firsthand how AFs
contribute to the non-linear transformations essential for NN learning.
This unit delves into the construction and utilization of custom layers in NNs. Custom layers are fundamental
components that allow for the extension and customization of NN architectures to better suit specific tasks. We will
explore several key custom layers, including FunctionLayer, ParametricRampLayer, SoftmaxLayer, NetEncoder,
and NetDecoder. Key topics covered in this unit include an overview of custom layers and their role in NN design, a
detailed exploration of FunctionLayer and how it allows for the definition of arbitrary functions within a network,
understanding ParametricRampLayer and its use for implementing piecewise linear functions, an examination of
SoftmaxLayer for transforming raw network outputs into probability distributions, and insights into NetEncoder and
NetDecoder for preprocessing input data and postprocessing network outputs, respectively. By the end of this unit,
you will have a solid understanding of how to create and integrate custom layers into NNs, enhancing their flexibility
and capability to tackle a wide range of problems.
This unit provides a detailed comparison of several commonly used AFs. We will analyze the characteristics and
performance implications of ReLU, ELU, SELU, GELU, Swish, HardSwish, Mish, SoftPlus, HardTanh,
HardSigmoid, Sigmoid, and Tanh. Each AF will be examined in terms of its mathematical formulation, gradient
behavior, and suitability for different types of NN architectures. Through this comprehensive comparison, you will
gain a clear understanding of the strengths and weaknesses of various AFs, enabling you to make informed decisions
when designing and optimizing NNs.
By the end of this chapter, you will have a robust understanding of how AFs shape the learning dynamics of NNs
and how custom layers can be leveraged to build more sophisticated and efficient models.
466
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Unit 9.1
Interactive Exploration of Activation Functions
(* Highlight the points on the curves for the current input value: *)
Epilog->{
Red,
PointSize[0.03],
Point[{{inputValue,logisticFunction[inputValue]},{inputValue,logisticDerivative[i
nputValue]}}]
},
PlotLabel->Style[Row[{"Logistic Function and Derivative at Input Value:
",inputValue}],10,Bold],
GridLines->Automatic,
ImageSize->270
],
467
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
468
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Point[{0,1}]
}
],
(* Create a slider to adjust the steepness parameter k from 0.1 to 10: *)
{{k,1,"Steepness Parameter (k)"},0.1,10,0.1}
]
Output
469
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Plot the shifted Unit Step function and the logistic sigmoid function:
*)
Plot[
{UnitStep[x-threshold],logisticSigmoid[x]},
{x,-5,5},
PlotLegends->Placed[{"Shifted Step Function","Logistic Sigmoid"},Below],
AxesLabel->{"x","y"},
PlotRange->{All,{0,1}},
PlotStyle->Thick,
GridLines->Automatic,
ImageSize->250
]
}
],
(* Display the current threshold value*)
Row[{"Threshold: ",threshold}]}
],
(*Create a slider to adjust the threshold value from-5 to 5*)
{{threshold,0,"Threshold"},-5,5,Appearance->"Labeled"}
]
Output
470
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
sigmoidDerivative[x_]:=sigmoid[x]*(1-sigmoid[x])
tanhDerivative[x_]:=1-tanh[x]^2
Output
Output
Manipulate[
Module[
471
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{penalizedTanh,plotRange},
(* Add a label for the plot showing the current value of alpha: *)
PlotLabel->Row[{"Penalized Tanh Activation (α = ",alpha,")"}]
]
],
Output
472
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Manipulate[
Plot[
{softRootSign[x,α,β],softRootSignDerivative[x,α,β]},
{x,-10,10},
PlotRange->{-2,3},
PlotLabel->StringForm["Soft-Root-Sign for α = `1`, β = `2`",α,β],
PlotLegends->Placed[{"SRS","SRS'"},Below],
ImageSize->250,
GridLines->Automatic
],
(* Create sliders to adjust the hyperparameter α and β: *)
{{α,1.6,"α"},1,3,0.1},
{{β,1.5,"β"},0.5,2.5,0.1}
]
Output
473
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Orange,
Line[{{-1/slope,-1},{1/slope,1}}],
Red,
PointSize[0.02],
Point[{0,relu[0]}]
},
PlotRange->{-1,1},
(*Add a label for the plot with the current slope value*)
PlotLabel->Row[{"ReLU function and Possible Slopes at x=0 (Slope =
",NumberForm[slope,{3,2}],")"}],
AxesLabel->{"x","f(x)"},
ImageSize->310,
GridLines->Automatic
],
(* Create a slider to adjust the slope from 0.01 to 1 with a step of 0.1: *)
{{slope,0.5,"slope"},0.01,1,0.1}
]
Output
474
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{ReLUFunction[x],PReLUFunction[x,alpha]},
{x,-3,3},
PlotRange->{-3,3},
PlotLegends->Placed[{"ReLU","PReLU"},Below],
Epilog->Text["α = "<>ToString[alpha],{2,1.5}],
PlotLabel->"ReLU and PReLU Activation Functions",
ImageSize->250 ,
GridLines->Automatic
],
(* Slider to adjust the alpha parameter: *)
{{alpha,0.01,"α"},0,1,0.01}
]
Output
475
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Plot[
{ParameterizedRandomReLU[x,alpha1],(* First RReLU function with alpha1: *)
ParameterizedRandomReLU[x,alpha2],(* Second RReLU function with alpha2: *)
ReLUFunction[x] (* Standard ReLU function: *)},
{x,-2,2},
PlotRange->{-2,2},
Filling->{1->{2}},
PlotLegends->Placed[{"First RReLU","Second RReLU","ReLU"},Below],
FillingStyle->{LightGray,Opacity[0.3]},
GridLines->Automatic,
ImageSize->300
],
(* Slider to adjust the first alpha parameter: *)
{{alpha1,initialAlpha1,"Alpha 1"},0,1,0.01},
(* Slider to adjust the second alpha parameter: *)
{{alpha2,initialAlpha2,"Alpha 2"},0,1,0.01}
]
Output
(* Define the Random Transformed ReLU activation function with a random offset (a):
*)
RandomTransformedReLU[x_,a_]:=If[x+a>0,x+a,0]
(* Create a dynamic interface to manipulate the random seed and standard deviation
parameters: *)
Manipulate[
476
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Generate a new random offset based on the Gaussian distribution with mean 0
and standard deviation sigma: *)
a=RandomVariate[NormalDistribution[0,sigma]];
(* Plot the Random Transformed ReLU and standard ReLU functions on the same graph:
*)
Plot[
{RandomTransformedReLU[x,a],ReLUFunction[x]},
{x,-5,5},
PlotRange->{Automatic,{-5,5}},
PlotLegends->Placed[{"RTReLU","ReLU"},Below],
PlotStyle->{Thick,Automatic},
GridLines->Automatic,
477
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
which updates in real-time, displays the displaced ReLU, standard ReLU, and ELU
functions over a specified range, enabling users to visually compare them: *)
(* Define the ELU (Exponential Linear Unit) activation function with parameter
alpha: *)
ELUFunction[x_,alpha_]:=If[x>=0,x,alpha*(Exp[x]-1)]
(* Create Manipulate: *)
Manipulate[
(* Plot the displaced ReLU, standard ReLU, and ELU functions on the same graph:
*)
Plot[
{displacedReLU[x,delta],ReLUFunction[x],ELUFunction[x,1]},
{x,-3,3},
PlotLegends->Placed[{"Displaced ReLU","ReLU","ELU"},Below],
PlotRange->{{-3,3},{-1.5,3}},
GridLines->Automatic,
ImageSize->300
],
(* Slider to adjust the delta parameter: *)
{{delta,0.5,"Delta"},0,1,0.1}
]
Output
478
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{elasticReLUFunction[x],lowerBoundFunction[x,alpha],upperBoundFunction[x,alpha]},
{x,-5,5},
PlotLegends->Placed[{"EReLU","(1-α)x","(1+α)x"},Below],
(* Filling between the lower and upper bounds: *)
Filling->{2->{3}},
PlotRange->{-2,5},
PlotLabel->"Elastic ReLU Activation Function",
ImageSize->300,
GridLines->Automatic,
PlotStyle->Thick
],
(* Slider for alpha parameter: *)
{{alpha,0.5,"Alpha"},0,1,0.01},
(* Slider for seed value: *)
{{randomSeed,1,"Seed"},1,100,1}
]
Output
479
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{elasticPReLUFunction[x,a],lowerBoundEPReLU[x,alpha],upperBoundEPReLU[x,alpha]},
{x,-5,5},
PlotLegends->Placed[{"EPReLU","(1-α)x","(1+α)x"},Below],
480
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
481
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
upperBoundNegative[x,alpha2],
lowerBoundNegative[x,alpha2]
},
{x,-3,3},
Filling->{2->{3},4->{5}},
PlotRange->{-2,2},
PlotLabel->"Adaptive Linearized Sigmoidal Activation Function",
ImageSize->300,
GridLines->Automatic,
PlotStyle->Thick
],
(* Slider for alpha1 parameter: *)
{{alpha1,0.4,"Alpha1"},0.1,2,0.1},
(* Slider for alpha2 parameter: *)
{{alpha2,0.4,"Alpha2"},0,2,0.1}
]
Output
482
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{Tanh'[λplus],x>=λplus},
(* Hyperbolic tangent region derivative: *)
{Sech[x]^2,λminus<x<λplus},
(* Left linear region derivative: *)
{Tanh'[λminus],x<=λminus}
}
]
(* Create Manipulate for interactive exploration: *)
Manipulate[
Row[
{
Plot[
{reLTanh[x,λplus,λminus],Tanh[x]},
{x,-5,5},
PlotRange->{-1.5,1.5},
Filling->{1->{2}},
PlotLabel->"ReLTanh and Tanh Activation Functions",
PlotLegends->Placed[{"ReLTanh","Tanh"},{0.75,0.2}],
GridLines->Automatic,
ImageSize->250
],
Plot[
{reLTanhDerivative[x,λplus,λminus],1-Tanh[x]^2},
{x,-5,5},
PlotRange->{-1.5,1.5},
Filling->{1->{2}},
PlotLabel->"The derivative of ReLTanh and Tanh",
PlotLegends->Placed[{"ReLTanh'","Tanh'"},{0.75,0.2}],
GridLines->Automatic,
ImageSize->250
]
}
],
(* Slider for λplus parameter: *)
{{λplus,1,"λplus (Threshold)"},0,3,0.1},
(* Slider for λminus parameter: *)
{{λminus,-1,"λminus (Threshold)"},-3,0,0.1}
]
Output
483
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
484
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
485
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
486
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
487
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
488
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Define the lower bound function for the Elastic Parametric ReLU (EPReLU): *)
lowerBound[x_,σ_]:=Piecewise[{{(kValue-σ) x,x>0},{"",x<0}}];
(* Define the upper bound function for the Elastic Parametric ReLU (EPReLU): *)
upperBound[x_,σ_]:=Piecewise[{{(kValue+σ) x,x>0},{"",x<0}}];
489
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{{β,1,"β"},0.1,2,0.1},
Output
490
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
SeedRandom[seed];
(* Define the lower bound function for the Elastic Parametric ReLU (EPReLU): *)
lowerBound[x_,σ_]:=Piecewise[{{(kValue-σ) x,x>0},{"",x<0}}];
(* Define the upper bound function for the Elastic Parametric ReLU (EPReLU): *)
upperBound[x_,σ_]:=Piecewise[{{(kValue+σ) x,x>0},{"",x<0}}];
491
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Manipulate[
Module[
{swishFun,swishDerivativeFun},
(* Define the Swish function: *)
swishFun[x_]:=x*LogisticSigmoid[β*x];
(* Define the derivative of the Swish function: *)
swishDerivativeFun[x_]:=Module[
{s},
s=LogisticSigmoid[β*x];
(*Compute the derivative*)
s+x*β*s*(1-s)
];
(* Plot the Swish function and its derivative: *)
Plot[
{swishFun[x],swishDerivativeFun[x]},
{x,-5,5},
PlotLegends->Placed[{"Swish","Swish Derivative"},Below],
PlotRange->{-0.5,2},
PlotLabel->"Swish and Its Derivatives",
ImageSize->300,
GridLines->Automatic
]
],
492
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Manipulate[
Module[
{eswish,eswishDerivative},
493
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
494
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
495
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{{alpha,1.702,"Alpha (SGELU)"},0.5,2,Appearance->"Labeled"},
Output
(* The Maxout function approximates the convex function formed by the maximum of
f1(x) and f2(x). By adjusting the parameters w1, b1, w2, and b2, you can see how
the Maxout unit approximates this convex function through different linear
segments. The dashed lines represent the linear functions f1(x) and f2(x),
respectively: *)
496
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
PlotStyle->{Dashed,Dashed,Directive[Opacity[0.5],Thick]},
PlotLegends->Placed[{"f1","f2","Maxout"},Below],
PlotLabel->"Maxout Unit and Linear Functions",
(* Highlight points on f1 and f2 at x=1*)
Epilog->{
PointSize[0.02],
Point[{{1,f1[1,w1,b1]},{1,f2[1,w2,b2]}}]
},
ImageSize->300,
GridLines->Automatic
],
(* Sliders to adjust the parameters of the linear functions: *)
{{w1,1,"w1"},-2,2},
{{b1,0,"b1"},-2,2},
{{w2,0,"w2"},-2,2},
{{b2,0,"b2"},-2,2}
]
Output
(* In this code, you can adjust the parameters w1, b1, w2, b2, w3, and b3 to see
how the Maxout unit approximates the convex function formed by the maximum of
f1(x), f2(x) and f3(x). The dashed lines represent the linear functions f1(x),
f2(x) and f3(x), respectively: *)
497
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
f1[x_,w1_,b1_]:=w1 x+b1
f2[x_,w2_,b2_]:=w2 x+b2
f3[x_,w3_,b3_]:=w3 x+b3
498
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
sliders. The interface displays the inputs and their corresponding softmax
probabilities in a grid, visualizes the probabilities using a bar chart, and plots
the softmax activation function over a specified range: *)
(* Define the softmax function: The softmax function converts a vector of values
into a vector of probabilities,where each probability is proportional to the
exponent of the corresponding input value: *)
softmax[inputs_]:=Module[
{expInputs,expSum},
(* Calculate the exponent of each input: *)
expInputs=Exp[inputs];
(* Sum of all exponentiated inputs: *)
expSum=Total[expInputs];
(* Normalize by dividing each exponentiated input by the sum: *)
expInputs/expSum
]
(* Create an interactive Manipulate interface to adjust the input values and display
the softmax probabilities: *)
Manipulate[
Module[
{inputs,probabilities},
(* Define the input vector: *)
inputs={x,y,z};
(* Calculate the softmax probabilities: *)
probabilities=softmax[inputs];
Column[
{
(*Display the inputs and their corresponding softmax probabilities in a grid:*)
Grid[
{
{"Inputs","Softmax Probabilities"},
{inputs,probabilities}
}
],
(* Visualize the softmax probabilities using a bar chart: *)
BarChart[
probabilities,
ChartLabels->Range[3],
PlotRange->{0,1},
ChartStyle->"Rainbow",
AxesLabel->{"Class","Probability"},
PlotLabel->"Softmax Probabilities",
ImageSize->300
],
(* Plot the softmax activation function:*)
Plot[
Evaluate[softmax[{x,y,z}]],
{x,-3,3},
PlotRange->{{-3,3},{0,1}},
PlotStyle->{Purple,Green,Red},
PlotLabel->"Softmax Activation Function",
ImageSize->300 ,
GridLines->Automatic
]
}
]
],
(* Sliders to adjust the input values x, y, and z: *)
{{x,1,"Input x"},-3,3,Appearance->"Labeled"},
{{y,0,"Input y"},-3,3,Appearance->"Labeled"},
499
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{{z,-1.0,"Input z"},-3.0,3.0,Appearance->"Labeled"}
]
Output
(* Define the Exponential Linear Unit (ELU) function with parameter beta:*)
eluFunction[x_,beta_]:=If[x>0,x,beta*(Exp[x]-1)]
(* Define the mixed activation function: Combine LReLU and ELU using a weighted
sum controlled by parameter Rho *)
mixedActivation[x_,Rho_,alpha_,beta_]:=Rho*lreluFunction[x,alpha]+(1-
Rho)*eluFunction[x,beta]
500
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
derivativeMixedActivation[x_,Rho_,alpha_,beta_]:=D[mixedActivation[t,Rho,alpha,be
ta],t]/. t->x
501
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
lreluResult=lreluFunction[x,alpha];
eluResult=eluFunction[x,beta];
502
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
GridLines->Automatic
]
],
(* Sliders to adjust the parameters omega, alpha, and beta: *)
{{omega,0.5,"Omega"},0,1,0.01},
{{alpha,0.5,"Alpha LReLU"},0,1,0.01},
{{beta,0.5,"beta ELU"},0,2,0.01}
]
Output
503
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
PlotRange->All,
AxesLabel->{"x","h(x)"},
PlotLabel->"Adaptive Piecewise Linear Unit (APL)",
ImageSize->300 ,
GridLines->Automatic
],
(* Sliders to adjust the parameters aValues and bValues: *)
Output
504
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
505
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
506
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
507
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
508
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
(* Define the Smoothing Function: This function applies a cosine smoothing within
the range -τ to τ. Outside this range, the function returns 0: *)
smoothingFunction[x_,τ_]:=If[-τ<=x<=τ,1/(2 τ) (1+Cos[(π/τ) x]),0]
(* Define the Smoothed Activation Function: This function computes the sum of
individual terms, each term is the product of a learnable parameter yi and the
smoothing mask r(x-xi,t s): *)
509
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
smoothedActivation[x_,anchorPoints_,t_,s_]:=Module[
{xi,yi},
(* Extract x-coordinates of anchor points: *)
xi=anchorPoints[[All,1]];
(* Extract y-coordinates of anchor points: *)
yi=anchorPoints[[All,2]];
Sum[
(* Compute each term of the sum: *)
anchorPoints[[i,2]]* smoothingFunction[x-anchorPoints[[i,1]],t s],
{i,1,Length[xi]}
]
]
(* Example anchor points: Generate random y-values for anchor points spaced between-
10 and 10: *)
anchorPoints=Table[{i,RandomReal[{0,10}]},{i,-10,10,1}];
(* Extract x-coordinates of anchor points: *)
xi=anchorPoints[[All,1]];
(* Plot the smoothed activation function using the random anchor points: *)
Plot[
smoothedActivation[x,anchorPoints,1,1],
{x,-10,10},
PlotRange->All,
PlotLabel->"Smoothed Activation Function (21 Random Anchor Points)",
Epilog->{Red,PointSize[0.01],Point[anchorPoints]},
ImageSize->300
]
(* Plot the smoothed activation function along with individual cosine smoothing
functions and scaled cosine smoothing functions for comparison: *)
Plot[
{
(*Smoothed activation function*)
smoothedActivation[x,anchorPoints,1,1],
(*Individual cosine smoothing functions*)
510
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Table[
smoothingFunction[x-anchorPoints[[i,1]],1],
{i,1,Length[xi]}
],
(*Scaled cosine smoothing functions*)
Table[
anchorPoints[[i,2]] *smoothingFunction[x-anchorPoints[[i,1]],1],
{i,1,Length[xi]}
]
},
{x,-10,10},
PlotRange->All,
PlotLabel->"Activation Function with Cosine Smoothing",
Epilog->{Red,PointSize[0.01],Point[anchorPoints]},
ImageSize->300,
PlotLegends->{"Smoothed Activation (Random Anchor Points)","21 Cosine Smoothing
Functions","21 Scaled Cosine Smoothing Functions"}
]
Output
Output
Output
511
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
512
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{{σ1,1,"σ1"},0.1,2,0.1,Appearance->"Labeled"},
{{λ2,0.5,"λ2"},0.1,2,0.1,Appearance->"Labeled"},
{{μ2,2,"μ2"},-5,5,0.1,Appearance->"Labeled"},
{{σ2,0.5,"σ2"},0.1,2,0.1,Appearance->"Labeled"},
{{λ3,0.3,"λ3"},0.1,2,0.1,Appearance->"Labeled"},
{{μ3,-3,"μ3"},-5,5,0.1,Appearance->"Labeled"},
{{σ3,0.8,"σ3"},0.1,2,0.1,Appearance->"Labeled"}
]
Output
513
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
ImageSize->300,
GridLines->Automatic
],
(* Slider to adjust the parameters a: *)
{{a,0,"a"},-10,10,0.1,Appearance->"Labeled"}
]
Output
(* Define the derivative of the logistic sigmoid function with respect to'x': *)
σLogisticDerivativeX[x_]:=σLogistic[x] (1-σLogistic[x])
(* Define the derivative of the logistic sigmoid function with respect to'a': *)
σLogisticDerivativeA[x_,a_]:=σLogistic[x+a] (1-σLogistic[x+a])
514
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{σBDAA2[x,a],σBDAA2DerivativeX[x,a],σBDAA2DerivativeA[x,a]},
{x,-15,15},
PlotRange->All,
PlotLegends->Placed[{"σBDAA2(x)","Derivative with x","Derivative with
a"},Below],
PlotLabel->Row[{"a = ",a}],
AxesLabel->{"x","σBDAA2(x)"},
ImageSize->300,
GridLines->Automatic
],
(* Slider to adjust the parameters a: *)
{{a,5,"a"},-10,10,0.1,Appearance->"Labeled"}
]
Output
(* Define the derivative of the logistic sigmoid function with respect to'x': *)
σLogisticDerivativeX[x_]:=σLogistic[x] (1-σLogistic[x])
(* Define the derivative of the logistic sigmoid function with respect to'a': *)
σLogisticDerivativeA[x_,a_]:=σLogistic[x+a] (1-σLogistic[x+a])-σLogistic[x-a] (1-
σLogistic[x-a])
515
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
(* Define the derivative of the logistic sigmoid function with respect to 'x': *)
σLogisticDerivativeX[x_]:=σLogistic[x] (1-σLogistic[x])
516
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
σBDAA3DerivativeX[x_,a_]:=1/2 (σLogisticDerivativeX[x+a]+σLogisticDerivativeX[x-
a])
(* Define the derivative of σBDAA4 with respect to 'x' using the chain rule: *)
σBDAA4DerivativeX[x_,a_]:= σBDAA3DerivativeX[x,a]
(* Define the derivative of the logistic sigmoid function with respect to 'a': *)
σLogisticDerivativeA[x_,a_]:=σLogistic[x+a] (1-σLogistic[x+a])-σLogistic[x-a] (1-
σLogistic[x-a])
(* Define the derivative of σBDAA4 with respect to'a' using the chain rule: *)
σBDAA4DerivativeA[x_,a_]:= σBDAA3DerivativeA[x,a]
Output
517
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Unit 9.2
Custom Layers in Neural Networks
In the ever-evolving field of deep learning, the Wolfram Language provides a comprehensive suite of tools for
constructing, training, and deploying neural networks. Mathematica, with its powerful symbolic and numerical
capabilities, offers a rich set of built-in functions that simplify the creation of complex neural network architectures.
This unit delves into some of these fundamental components, including FunctionLayer, ParametricRampLayer,
SoftmaxLayer, NetEncoder, and NetDecoder.
FunctionLayer
ElementwiseLayer is designed for situations where you need to apply a function to each element of an input tensor
independently. This layer is highly useful for implementing common activation functions (such as ReLU, sigmoid, and
tanh) as well as custom transformations. By applying functions element-wise, you can tailor the behavior of your
neural network to fit your specific needs, enhancing its performance and interpretability. On the other hand,
FunctionLayer takes customization a step further by allowing you to define layers based on arbitrary functions that
can operate on entire tensors. This is particularly useful when your desired transformation involves complex
operations, multiple inputs, or non-standard tensor manipulations that go beyond element-wise operations.
FunctionLayer[f]
represents a net layer that applies function f to its input.
Remarks:
• FunctionLayer is used to define neural nets from usual Wolfram Language code.
• FunctionLayer[f][x] behaves in the same way as f[x].
• The function f should involve only valid operations on arrays that produce an array or an association of
arrays.
• Valid operations include arithmetic functions (Plus, Times, etc.), elementary functions (Exp, Sqrt, Sin, etc.),
numerical functions (Min, Round, Ramp, etc.), array constructions (Table, ConstantArray, etc.), array
operations (Dot, Det, Tr, etc.), descriptive statistics (Mean, StandardDeviation, etc.) and distance and
similarities (EuclideanDistance, HammingDistance, etc.). It is also possible to use looping constructs (Map,
NestList, FoldList, etc.) and list manipulation functions (Part, Reverse, etc.).
• Function f must take only one argument as input. The argument can be an array or an association of arrays.
• If the argument of f is a unique array, f can be defined by a pure function, a symbol or a composition of these.
The resulting layer will have a unique input port called "Input".
• FunctionLayer can also be given a multiple-argument function f using the syntax
FunctionLayer[Apply[f]]. In this case, ports are named automatically.
• FunctionLayer[f,"port"->shape] can be used as in NetGraph to specify the shape, encoder or decoder of
a given port.
518
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Calculate the standard deviation of the given list of numbers using the
FunctionLayer: *)
stdLayerResult=stdLayer[{1.3,2.1,2,3.56,2.4,4.31,6.35,7.,8.2}]
Output
Output 2.49366
Output 2.49366
Output StandardDeviation
Output
Output
519
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
matrix, applies both the custom function and the `FunctionLayer` to this matrix,
and computes the same statistical measures directly using Mathematica's built-in
functions. Finally, it compares the results from these three methods to ensure
consistency and accuracy in the computation of the statistical measures: *)
(* Apply the function directly to the input matrix to compute the statistical
measures: *)
statisticalMeasuresFunctionResult=statisticalMeasuresFunction[inputMatrix];
(* Apply the FunctionLayer (as a NetGraph) to the input matrix to compute the
statistical measures: *)
statisticalMeasuresLayerResult=statisticalMeasuresLayer[inputMatrix];
(* Compare the results from the function, FunctionLayer, and direct methods: *)
comparisonResults=<|
"Function"->statisticalMeasuresFunctionResult,
"FunctionLayer"->statisticalMeasuresLayerResult,
"Direct"-><|
"Mean"->meanResult,
"Variance"->varianceResult,
"StandardDeviation"->standardDeviationResult,
"Median"->medianResult,
"Min"->minResult,
"Max"->maxResult
|>
|>
520
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Output {
{1.73205,2.23607,2.64575},
{2.,2.44949,2.82843},
{2.23607,2.64575,3.},
{2.44949,2.82843,3.16228},
{2.64575,3.,3.31662},
{2.82843,3.16228,3.4641},
{3.,3.31662,3.60555}
}
Output <|
Function->
<|
Mean->{2.41311,2.80552,3.1461},
Variance->{0.20637,0.150568,0.119028},
StandardDeviation->{0.454279,0.388031,0.345005},
Median->{2.44949,2.82843,3.16228},
Min->1.73205,
Max->3.60555
|>,
FunctionLayer->
<|
Mean->{2.41311,2.80552,3.1461},
Variance->{0.20637,0.150568,0.119029},
521
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
StandardDeviation->{0.454279,0.388031,0.345005},
Median->{2.44949,2.82843,3.16228},
Min->1.73205,
Max->3.60555
|>,
Direct->
<|
Mean->{2.41311,2.80552,3.1461},
Variance->{0.20637,0.150568,0.119028},
StandardDeviation->{0.454279,0.388031,0.345005},
Median->{2.44949,2.82843,3.16228},
Min->1.73205,
Max->3.60555
|>
|>
(* Create a NetGraph using a FunctionLayer that computes the total sum of its
input: *)
totalLayer=NetGraph@FunctionLayer[Total]
522
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Output
Output
523
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output {2.5,1.5,5.7,7.2,11.1}
Output {0.170088,0.102053,0.3878,0.489853,0.755189}
Output {0.000179614,0.0000660761,0.00440637,0.019748,0.9756}
Output 1.90498
Output 1.
Output {0.170088,0.102053,0.3878,0.489853,0.755189}
Output {0.000179614,0.0000660762,0.00440638,0.019748,0.9756}
Output 1.90498
Output 1.
Output <|
NormalizationLayer->{0.170088,0.102053,0.3878,0.489853,0.755189},
DirectNormalization->{0.170088,0.102053,0.3878,0.489853,0.755189},
TotalNormalizationLayer->1.90498,
DirectTotalNormalization->1.90498,
ExponentialNormalizationLayer-
>{0.000179614,0.0000660761,0.00440637,0.019748,0.9756},
DirectExponentialNormalization-
>{0.000179614,0.0000660762,0.00440638,0.019748,0.9756},
TotalExponentialNormalizationLayer->1.,
DirectTotalExponentialNormalization->1.
|>
(* Compare the results from the FunctionLayer and the direct method: *)
comparisonResults=<|"StandardizationFunctionLayer"-
>standardizationLayerResult,"DirectStandardization"-
>directStandardizationResult|>
524
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Output
Output {1.5,2.3,3.7,4.2,5.1}
Output 5.36442*10^-8
Output 1.
Output <|
StandardizationFunctionLayer->{-1.28108,-0.73008,0.234177,0.578554,1.19843},
DirectStandardization->{-1.28108,-0.73008,0.234177,0.578554,1.19843}
|>
525
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Compare the results from the FunctionLayers and the direct methods: *)
comparisonResults=<|
"EuclideanDistanceFunctionLayer"->euclideanDistanceResult,
"DirectEuclideanDistance"->directEuclideanDistanceResult,
"ManhattanDistanceFunctionLayer"->manhattanDistanceResult,
"DirectManhattanDistance"->directManhattanDistanceResult|>
Output
Output {{1.,2.},{4.,6.}}
Output <|
EuclideanDistanceFunctionLayer->5.,
DirectEuclideanDistance->5.,
ManhattanDistanceFunctionLayer->7.,
DirectManhattanDistance->7.
|>
ParametricRampLayer
ParametricRampLayer[]
represents a net layer that computes a leaky ReLU activation with a slope that can be learned.
ParametricRampLayer[levels]
specifies the levels on which each dimension has a specific slope.
526
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Remarks:
• The slope is a coefficient of leakage applied to input negative values.
• By default, the slope is initialized to 0.1.
• ParametricRampLayer["Slope"->value,LearningRateMultipliers->0] is a leaky ReLU with a fixed
slope.
• ParametricRampLayer exposes the following ports for use in NetGraph etc.:
• When it cannot be inferred from other layers in a larger net, the option "Input"->{n1,n2,…} can be used to
fix the input dimensions of ParametricRampLayer.
Output
Output {0.1,0.1,0.1,0.1}
Output {
{-0.3,-0.2,-0.1,-0.4},
{0.,2.,1.,4.}
}
527
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Output {-0.0547273,-0.0223373,0.129081,-0.369611}
Output
528
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Output {0.1}
(* Apply the initialized layer to a set of input vectors,observing how the layer
transforms the inputs: *)
prelu[{{-1,-1,-1,-1},{1,1,1,1}}]
Output
Output {
{-0.1,-0.3,-0.4,-0.5},
{1.,1.,1.,1.}
}
SoftmaxLayer
SoftmaxLayer[]
represents a softmax net layer.
SoftmaxLayer[n]
represents a softmax net layer that uses level n as the normalization dimension.
Remarks:
• SoftmaxLayer[…][input] explicitly computes the output for input.
• SoftmaxLayer[…][{input1,input2,…}] explicitly computes outputs for each of the inputi.
• SoftmaxLayer is typically used inside NetChain, NetGraph, etc. to normalize the output of other layers in
order to use them as class probabilities for classification tasks.
529
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
• When it cannot be inferred from other layers in a larger net, the option "Input"->n can be used to fix the
input dimensions of SoftmaxLayer.
• SoftmaxLayer[] is equivalent to SoftmaxLayer[-1].
• SoftmaxLayer effectively normalizes the exponential of the input array, producing vectors that sum to 1.
For the default level of -1, the innermost dimension is used as the normalization dimension.
• When SoftmaxLayer[-1] is applied to a vector v, it produces the vector Normalize[Exp[v],Total]. When
applied to an array of higher dimension, it is mapped onto level -1.
• When SoftmaxLayer[n] is applied to a k-dimensional input array x_(d_(1) ... d_(k)), it produces the array
, where n is the summed-over index of x.
Output
530
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Total[softmaxOutput]
Output {0.0320586,0.0871443,0.236883,0.643914}
Output 1.
(* Compute and display the total of the Softmax output, which should be 1: *)
outputSum=Total[softmaxOutput]
Output
Output {0.0320586,0.0871443,0.236883,0.643914}
Output 1.
(* Compute and display the total of each row of the Softmax output: *)
rowSums=Map[Total,softmaxOutput]
531
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Output ({
{0.731059, 0.268941},
{0.0474259, 0.952574},
{0.00247262, 0.997527},
{0.952574, 0.0474259}
})
Output {1.,1.,1.,1.}
Output
Output {0.0320586,0.0871443,0.236883,0.643914}
Output {0.0900306,0.244728,0.665241}
Output {0.268941,0.731059}
NetEncoder
NetEncoder["name"]
represents an encoder that takes a given form of input and encodes it as an array for use in a net.
532
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
NetEncoder[{"name",…}]
represents an encoder with additional parameters specified.
Remarks:
• NetEncoder[…][input] gives the specified encoding for input.
• NetEncoder[…][{input1,input2, …}] explicitly computes outputs for each of the inputi.
• Possible named encoders include:
• A NetEncoder object can be attached to an input port of a net by specifying "port"->NetEncoder[…] when
constructing the net. Specifying "port"->"name" will create an encoder using NetEncoder["name"] and
attach it.
NetDecoder
NetDecoder["name"]
represents a decoder that takes a net representation and decodes it into an expression of a given form.
NetDecoder[{"name",…}]
represents a decoder with additional parameters specified.
Remarks:
• NetDecoder[…][array] gives the specified decoded form for array.
• NetDecoder[…][{array1,array2, …}] explicitly computes outputs for each of the arrayi.
• NetDecoder[…][…,prop] can be used to calculate a specific property for the input data.
• NetDecoder[…][…,"Properties"] gives the possible properties.
• Possible named decoders include:
533
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
• A NetDecoder object can be attached to an output port of a net by specifying "port"->NetDecoder[…] when
constructing the net. Specifying "port"->"type" will create a decoder of the given type and attach it.
(* Create a class encoder for gender classification with classes "male" and
"female": *)
genderEncoder=NetEncoder[{"Class",{"male","female"}}]
Output
Output 1
Output 2
Output {1,2,2,1}
534
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Output 2
Output {1,2,3}
Output {2,1,3,3,1}
Output
Output 1
Output 0
Output {1,0,1}
(* Create a decoder for classifying numerical outputs into classes "a", "b", and
"c": *)
classDecoder=NetDecoder[{"Class",{"a","b","c"}}]
535
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
decodedClassList=classDecoder[
{
{0.9,0.0,0.1},
{0.9,0.1,0.0},
{0.1,0.9,0.0},
{0.0,0.9,0.1},
{0.0,0.1,0.9},
{0.1,0.0,0.9}
}
]
Output
Output a
Output {a,a,b,b,c,c}
Output
Output dog
Output {dog,dog}
536
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
conversion of numerical and binary data into meaningful Boolean values for further
analysis and decision-making: *)
decodedBoolean2=booleanDecoder[0.3]
decodedBooleanExplicit2=booleanDecoder[0]
Output
Output True
Output False
Output {True,False,True,False}
Output True
Output False
Output {True,False,True,False}
537
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Output c
Output {a,c}
Output <|a->0.665241,b->0.244728,c->0.0900306|>
Output {1.09861,0.0203172}
538
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Unit 9.3
Comparison of Some Activation Functions
Activation functions play a crucial role in neural networks by introducing non-linearity, which enables the networks
to learn complex patterns and representations. This unit provides a detailed comparison of several commonly used
activation functions (ReLU, ELU, SELU, GELU, Swish, HardSwish, Mish, SoftPlus, HardTanh, HardSigmoid,
Sigmoid, Tanh).
(* Loop through each activation function, train a neural network, and record the
results: *)
results=Table[
Module[
{net,trainedNet},
(* Define a simple neural network structure: *)
net=NetChain[
{
(* First hidden layer with specified activation function: *)
LinearLayer[10],ElementwiseLayer[functions],
(* Second hidden layer with specified activation function: *)
LinearLayer[10],ElementwiseLayer[functions],
(* Third hidden layer with specified activation function: *)
LinearLayer[10],ElementwiseLayer[functions],
(* Output layer with linear activation function: *)
LinearLayer[1]
}
];
(* Train the network on training data: *)
trainedNet=NetTrain[
539
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
net,
trainingData,
(* Monitor training progress using GradientsRMS property: *)
<|
"Property"->"GradientsRMS",
"Form"->"EvolutionPlot",
"PlotOptions"->{PlotLabel->Style[Row[{"GradientsRMS (Batch):
",functions}],10,Bold],ImageSize->300},
"Interval"->"Batch"
|>,
(* Specify mean squared loss as the training objective: *)
LossFunction->MeanSquaredLossLayer[],
(* Set the batch size for training: *)
BatchSize->64,
(* Learning rate for "ADAM": *)
LearningRate->0.01,
(* Use "ADAM" as the optimization method: *)
Method->"ADAM",
(* Maximum number of training iterations: *)
MaxTrainingRounds->50
]
],
(* Iterate over the grid of activation functions: *)
{functions,activationFunctions}
]
Output
540
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
541
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
"HardSigmoid","Sigmoid",Tanh
} ;
(* Loop through each activation function, train a neural network, and record the
results: *)
results=Table[
Module[
{net,trainedNet},
542
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
543
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Loop through each activation function, train a neural network, and record the
results: *)
results=Table[
Module[
{net,trainedNet},
544
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
545
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
546
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
"ReLU","ELU","SELU",
"GELU","Swish","HardSwish",
"Mish","SoftPlus","HardTanh",
"HardSigmoid","Sigmoid",Tanh} ;
(* Loop through each activation function, train a neural network, and record the
results: *)
results=Table[
Module[
{net,trainedNet},
547
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
548
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
549
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Loop through each activation function, train a neural network, and record the
results: *)
results=Table[
Module[
{net,trainedNet},
550
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
551
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
552
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Loop through each activation function, train a neural network, and record the
results: *)
results=Table[
Module[
{net,trainedNet,validationMSE},
553
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{activationFunctions[[i]],results[[i]][[1]]},
{i,1,12}]
(* Create overlays of loss plots and activation functions: *)
Table[
Overlay[{results[[i]][[3]],activationFunctions[[i]]},Alignment->{0.9,0.4}],
{i,1,12}
]
Output {{ReLU,0.0275686},{ELU,0.0247876},{SELU,0.0326586},{GELU,0.0247986},{Swish,0.0255
731},{HardSwish,0.0261176},{Mish,0.0253922},{SoftPlus,0.0254517},{HardTanh,0.0303
038},{HardSigmoid,0.0291263},{Sigmoid,0.030037},{Tanh,0.0281623}}
Output
554
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Assign labels based on whether the point's distance from the origin is less
than 0.5: *)
trainlabels=Thread[Map[Norm,trainpoints]<0.5];
(* Visualize the synthetic training set with different colors for each class: *)
ListPlot[
{
Pick[trainpoints,trainlabels,True],
Pick[trainpoints,trainlabels,False]
},
AspectRatio->1,
ImageSize->250,
PlotStyle->PointSize[Medium],
FrameLabel->{"X","Y","Synthetic Training Set"},
PlotLegends->{"Class 1","Class 2"}
]
(* Loop through each activation function, train a neural network, and record the
results: *)
results=Table[
Module[
{net,trainedNet},
555
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
556
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
557
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Assign labels based on whether the point's distance from the origin is less
than 0.5: *)
trainlabels=Thread[Map[Norm,trainpoints]<0.5];
(* Visualize the synthetic training set with different colors for each class: *)
ListPlot[
{
Pick[trainpoints,trainlabels,True],
Pick[trainpoints,trainlabels,False]
},
AspectRatio->1,
ImageSize->250,
PlotStyle->PointSize[Medium],
FrameLabel->{"X","Y","Synthetic Training Set"},
PlotLegends->{"Class 1","Class 2"}
]
(* Loop through each activation function, train a neural network, and record the
results: *)
results=Table[
Module[
{net,trainedNet},
558
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
LinearLayer[5],ElementwiseLayer[functions],
(* Second hidden layer with specified activation function: *)
LinearLayer[5],ElementwiseLayer[functions],
(* Output layer with logistic sigmoid activation function: *)
LinearLayer[],ElementwiseLayer[LogisticSigmoid]
},
"Output"->NetDecoder["Boolean"]
];
559
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
560
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Assign labels based on whether the point's distance from the origin is less
than 0.5: *)
trainlabels=Thread[Map[Norm,trainpoints]<0.5];
(* Assign labels using the same criteria as for the training set: *)
validationLabels=Thread[Map[Norm,validationPoints]<0.5];
(* Visualize the synthetic training set with different colors for each class: *)
ListPlot[
{
Pick[trainpoints,trainlabels,True],
Pick[trainpoints,trainlabels,False]
},
AspectRatio->1,
ImageSize->250,
PlotStyle->PointSize[Medium],
FrameLabel->{"X","Y","Synthetic Training Set"},
PlotLegends->{"Class 1","Class 2"}
]
561
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
(* Loop through each activation function, train a neural network, and record the
results: *)
results=Table[
Module[
{net,trainedNet},
562
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
{i,1,12}
]
Output
563
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
Output {{ReLU,0.0400866},{ELU,0.0340551},{SELU,0.0836259},{GELU,0.0274739},{Swish,0.0249
386},{HardSwish,0.0152379},{Mish,0.0221938},{SoftPlus,0.0558646},{HardTanh,0.4763
32},{HardSigmoid,0.0776821},{Sigmoid,0.104511},{Tanh,0.0634383}}
564
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output {{ReLU,0.984},{ELU,0.986},{SELU,0.964},{GELU,0.99},{Swish,0.99},{HardSwish,0.998}
,{Mish,0.994},{SoftPlus,0.976},{HardTanh,0.716},{HardSigmoid,0.968},{Sigmoid,0.97
},{Tanh,0.97}}
Output
565
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
566
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
Output
567
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
568
CHAPTER 9 ADVANCED ACTIVATION FUNCTIONS
569
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
CHAPTER 10
COMPLEX VALUED NEURAL NETWORKS
Remark:
This chapter provides a Mathematica implementation of the concepts and ideas presented in Chapter 9, [1], of the
book titled Artificial Neural Network and Deep Learning: Fundamentals and Theory. We strongly recommend that
you begin with the theoretical chapter to build a solid foundation before exploring the corresponding practical
implementation. This chapter also serves as a summary of the article titled Comprehensive Survey of Complex-
Valued Neural Networks: Insights into Backpropagation and Activation Functions. For more details about complex
valued activation functions, please refer to Ref [39].
In this chapter, we delve into the world of complex-valued activation functions (CVAFs) and their visualizations
using Mathematica. For a more comprehensive background, we refer to [39] and the references cited therein. The
ability to visualize these functions is crucial for gaining deeper insights into their behavior and understanding how
they transform complex inputs. By leveraging Mathematica's powerful visualization tools, we can explore the
intricacies of CVAFs in both two-dimensional and three-dimensional representations.
Three-dimensional plots are particularly useful for visualizing the magnitude and phase of complex functions.
Mathematica's ComplexPlot3D function is designed to generate a three-dimensional representation of the magnitude
of the function, Abs[f], while using color to indicate the argument, Arg[f], over a specified complex rectangle. This
type of plot provides a comprehensive view, allowing us to observe how the magnitude and phase of a CVAF vary
across the complex plane. We will demonstrate how to use ComplexPlot3D effectively to visualize various CVAFs,
providing detailed examples and techniques to enhance your understanding. These visualizations are invaluable for
analyzing the behavior of CVAFs, revealing patterns and characteristics that are not immediately apparent from the
mathematical formulation alone.
While three-dimensional plots offer a detailed perspective, two-dimensional visualizations are often more
accessible and easier to interpret for certain applications. The ComplexPlot function in Mathematica generates a two-
dimensional representation of Arg[f] over the complex rectangle, effectively mapping the phase of the function onto
a color gradient. This straightforward visualization technique is powerful for quickly assessing the function's behavior
on the complex plane. Throughout this chapter, we will explore how to utilize ComplexPlot to visualize CVAFs,
offering practical examples and tips for creating clear and informative plots. These two-dimensional visualizations
complement the three-dimensional ones, providing a different yet equally valuable perspective on the behavior of
CVAFs.
Interactivity is a key feature in Mathematica that allows for dynamic exploration of CVAFs. Using the `Manipulate`
function, we can create interactive visualizations where the parameters of the AFs can be adjusted in real-time. This
dynamic approach enables us to observe how changes in parameters affect the AFs, offering a hands-on way to explore
their behavior. Interactive simulations and visualizations facilitate a deeper understanding of the mathematical
underpinnings of CVAFs.
To provide a comprehensive resource, this chapter includes an extensive catalog of CVAFs, detailing their
definitions, properties, and visual representations. The catalog covers a wide range of AFs, including but not limited
to: Split-Step Function, Split-Sigmoid, Split-Parametric Sigmoid, Split-Tanh, Split-Sigmoid Tanh, Split-Hard Tanh,
Split-CReLU, Split-QAM, Amplitude-Phase-Type Function, Amplitude-Phase Sigmoidal Function, Complex
Cardioid, modReLU, Fully Complex Tanh, Fully Complex Logistic-Sigmoidal, Fully Complex Elementary
Transcendental Function (ETF), zReLU, z3ReLU, zPReLU, z3PreLU.
570
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Unit 10.1
Complex Numbers and Functions
(* Choose the range of c1 values for plotting hyperbolas of the form x^2-y^2=c1:
*)
c1Values={-4,-2,2,4};
(* Choose the range of c2 values for plotting hyperbolas of the form 2xy=c2: *)
c2Values={-4,-2,2,4};
571
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
Output
572
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
{gridPoints,mappedRealImag},
PlotStyle->{Directive[PointSize[0.012],Blue,
Opacity[0.3]],Directive[PointSize[0.01],Red,Opacity[0.3]]},
Frame->True,
PlotRange->Full,
PlotLegends->{"z-plane","f-plane"},
ImageSize->300
]
Output
Manipulate[
(* Define the complex mapping function: *)
f[z_]:=z^exp;
(* Define a function to extract real and imaginary parts: *)
getRealImag[expr_]:={Re[expr],Im[expr]};
(* Create a grid of points in the z-plane: *)
gridPoints=Flatten[
Table[
{x,y},
{x,-3,3,0.3},
{y,-3,3,0.3}
],
1
];
573
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
(* Manipulate controls: *)
{{exp,2,"Exponent"},0.1,3,0.1}
]
Output
(* Generate a grid of points from -2 to 2 on both real and imaginary axes with a
step of 0.4, excluding the origin*)
gridPoints=DeleteCases[
Flatten[
Table[
x+I y,
{x,-2,2,0.4},
{y,-2,2,0.4}
]
],
0+0. I
];
574
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
575
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
Output
f1[z_,a_,b_]:=(a z)^2+b
576
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
{transformedGrid1,transformedGrid2,gridPlotOriginal,gridPlotTransformed1,gridPlot
Transformed2},
577
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
Output
578
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
Output
579
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
580
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
ImageSize->300
]
Output
Output
581
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
Output
582
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
Manipulate[
Row[
{
ComplexPlot[
f[z],
{z,-2-2 I,2+2 I},
ColorFunction->"QuantileAbs",
PlotLegends->Automatic,
ImageSize->300
],
ComplexPlot3D[
f[z],
{z,-2-2 I,2+2 I},
ColorFunction->"CyclicLogAbs",
PlotRange->Full,
PlotLegends->Automatic,
ImageSize->300
]
}
]
,
{{f,Tanh},{Re,Im,Abs,Arg,Sin,Cos,Tan,Log,Tanh,ArcSinh,ArcTanh,Sqrt,Gamma}},
ControlType->SetterBar
]
583
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
584
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Unit 10.2
Complex Valued Activation Functions
Mathematica Code 10.18
Input (* The code defines and visualizes the Split-Step activation function for a complex
variable z=x+iy by applying the step function separately to its real and imaginary
parts. It introduces a modular function `createSplitStepPlot` to generate and
display 3D surface plots and slice contour plots for the real part, imaginary part,
magnitude, and phase of the Split-Step function. The generated plots are displayed
together, allowing for a comprehensive examination of the Split-Step function's
behavior across different components in the complex plane: *)
(* Define a function to create the plots for different components of the Split-
Step Function: *)
createSplitStepPlot[component_,label_]:=Module[
{plot1,slice},
(* Define a complex variable: *)
znumber=x+I*y;
(* Define the Split-Step Function: *)
σSSF[u_]:=If[u>=0,1,0];
σSplitStep:=σSSF[Re[znumber]]+I σSSF[Im[znumber]];
585
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
BoxRatios->{1,1,1},
FaceGrids->{Back,Left},
ImageSize->200
]
]
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
the Split-Step Function: *)
realSplitStepPlot=createSplitStepPlot[
Re[σSplitStep],
"Real Part of Split-StepF(z)"
];
imaginarySplitStepPlot=createSplitStepPlot[
Im[σSplitStep],
"Imaginary Part of Split-StepF(z)"
];
magnitudeSplitStepPlot=createSplitStepPlot[
Abs[σSplitStep],
"Magnitude of Split-StepF(z)"
];
phaseSplitStepPlot=createSplitStepPlot[
Arg[σSplitStep],
"Phase of Split-StepF(z)"
];
(*Display all four plots together in a list*)
{realSplitStepPlot,imaginarySplitStepPlot,magnitudeSplitStepPlot,phaseSplitStepPl
ot}
Output
586
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
(* Define a function to create the plots for different components of the Split-
Sigmoidal function: *)
createSplitSigmoidalPlot[component_,label_]:=Module[
{plot1,slice},
(* Define a complex variable: *)
587
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
znumber=x+I*y;
(* Define the split-sigmoidal activation function: *)
sigmoidalR[u_]:=1/(1+Exp[-u]);
splitsigmoidal:=sigmoidalR[Re[znumber]]+I sigmoidalR[Im[znumber]];
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
Split-Sigmoidal: *)
realSplitSigmoidalPlot=createSplitSigmoidalPlot[
Re[splitsigmoidal],
"Real Part of split-sigmoidalF(z)"
];
imaginarySplitSigmoidalPlot=createSplitSigmoidalPlot[
Im[splitsigmoidal],
"Imaginary Part of split-sigmoidalF(z)"
];
magnitudeSplitSigmoidalPlot=createSplitSigmoidalPlot[
Abs[splitsigmoidal],
"Magnitude of split-sigmoidalF(z)"
588
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
];
phaseSplitSigmoidalPlot=createSplitSigmoidalPlot[
Arg[splitsigmoidal],
"Phase of split-sigmoidalF(z)"
];
Output
589
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
ColorFunction->"CyclicLogAbsArg",
PlotLegends->Automatic,
BoxRatios->{1,1,1},
ImageSize->270
]
Output
(* Set parameters: *)
c1=0.7;
c2=3;
(* Define a function to create the plots for different components of the Split-
Parametric Sigmoidal CVAF: *)
createSplitPSigmoidalPlot[component_,label_]:=Module[
{plot1,slice},
(* Define a complex variable: *)
znumber=x+I*y;
(* Define the Split-Parametric Sigmoidal CVAF: *)
σSPSigmoidalR[znumber_,c1_,c2_]:=(2 c1)/(1+Exp[-c2 znumber])-c1;
σSPSigmoidal:=σSPSigmoidalR[x,c1,c2]+I σSPSigmoidalR[y,c1,c2];
590
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
591
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
{realSplitPSigmoidalPlot,imaginarySplitPSigmoidalPlot,magnitudeSplitPSigmoidalPlo
t,phaseSplitPSigmoidalPlot}
Output
Manipulate[
Module[
{plot1,slice,x,y},
(* Define a complex variable: *)
znumber=x+I*y;
(* Define the Split-Parametric Sigmoidal CVAF and its derivative: *)
σSPSigmoidalR[znumber_,c1_,c2_]:=(2 c1)/(1+Exp[-c2 znumber])-c1;
σSPSigmoidal:=σSPSigmoidalR[x,c1,c2]+I σSPSigmoidalR[y,c1,c2];
(* Generate the 3D plot of the magnitude of the Split-Parametric Sigmoidal CVAF:
*)
plot1=Plot3D[
Abs[σSPSigmoidal],
{x,-6,6},
{y,-6,6},
(* Plot options: *)
ClippingStyle->None,
AxesLabel->{"Re(z)","Im(z)"},
MeshFunctions->{#3&},
Mesh->15,
MeshStyle->Opacity[.5],
MeshShading->{{Opacity[.3],Blue},{Opacity[.8],Orange}},
Lighting->"Neutral"
592
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
];
(* Generate the slice contour plot of the magnitude of the Split-Parametric
Sigmoidal CVAF: *)
slice=SliceContourPlot3D[
Abs[σSPSigmoidal],
z==0,
{x,-6,6},
{y,-6,6},
{z,-1,1},
(* Plot options: *)
Contours->15,
Axes->False,
PlotPoints->50,
PlotRangePadding->0,
ColorFunction->"Rainbow"
];
(* Combine the 3D plot and the slice contour plot: *)
Show[
plot1,
slice,
PlotRange->All,
PlotLabel->"Magnitude of split-PsigmoidF(z)",
BoxRatios->{1,1,1},
FaceGrids->{Back,Left},
ImageSize->250
]
],
(* Interactive sliders for adjusting parameters c1 and c2: *)
{{c1,0.7,"c1"},0.1,5,0.1},
{{c2,3,"c2"},0.1,5,0.1}
]
Output
593
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
c2=3;
594
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
(* Define a function to create the plots for different components of the Split-
Tanh function: *)
createSplitTanhPlot[component_,label_]:=Module[
{plot1,slice},
(* Define a complex variable: *)
znumber=x+I*y;
(* Define the Split-Tanh function: *)
splitTanh:=Tanh[Re[znumber]]+I*Tanh[Im[znumber]];
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
Split-Tanh: *)
realSplitTanhPlot=createSplitTanhPlot[
Re[splitTanh],
"Real Part of split-Tanh(z)"
];
imaginarySplitTanhPlot=createSplitTanhPlot[
595
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Im[splitTanh],
"Imaginary Part of split-Tanh(z)"
];
magnitudeSplitTanhPlot=createSplitTanhPlot[
Abs[splitTanh],
"Magnitude of split-Tanh(z)"
];
phaseSplitTanhPlot=createSplitTanhPlot[
Arg[splitTanh],
"Phase of split-Tanh(z)"
];
Output
596
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
AxesLabel->{"Re(z)","Im(z)","SplitTanh(z)"},
ColorFunction->"CyclicLogAbsArg",
PlotLegends->Automatic,
BoxRatios->{1,1,1},
ImageSize->250
]
Output
(* Define a function to create the plots for different components of the Split-
Sigmoidal Tanh function: *)
createSplitSTanhPlot[component_,label_]:=Module[
{plot1,slice},
(* Define a complex variable: *)
znumber=x+I*y;
(* Define the Split-Sigmoidal Tanh function: *)
rePart=Tanh[Re[znumber]]/(1-(Re[znumber]-3) Exp[-Re[znumber]]);
imPart=Tanh[Im[znumber]]/(1-(Im[znumber]-3) Exp[-Im[znumber]]);
splitSTanh:=rePart+I imPart;
597
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
component,
{x,-6,6},
{y,-6,6},
(* Plot options: *)
ClippingStyle->None,
AxesLabel->{"Re(z)","Im(z)"},
MeshFunctions->{#3&},
Mesh->15,
MeshStyle->Opacity[.5],
MeshShading->{{Opacity[.3],Blue},{Opacity[.8],Orange}},
Lighting->"Neutral"
];
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
Split-Sigmoidal Tanh: *)
realSplitSTanhPlot=createSplitSTanhPlot[
Re[splitSTanh],
"Real Part of split-STanh(z)"
];
imaginarySplitSTanhPlot=createSplitSTanhPlot[
Im[splitSTanh],
"Imaginary Part of split-STanh(z)"
];
magnitudeSplitSTanhPlot=createSplitSTanhPlot[
Abs[splitSTanh],
"Magnitude of split-STanh(z)"
];
phaseSplitSTanhPlot=createSplitSTanhPlot[
Arg[splitSTanh],
598
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
"Phase of split-STanh(z)"
];
Output
599
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
ComplexPlot[
splitSTanh,
{z,-3-3 I,3+3 I},
(* Plot options: *)
PlotRange->All,
ColorFunction->"CyclicLogAbsArg",
PlotLegends->Automatic,
BoxRatios->{1,1,1},
ImageSize->200
]
Output
(* Define a function to create the plots for different components of the Split-
CReLU function: *)
createSplitCReLUPlot[component_,label_]:=Module[
{plot1,slice},
(* Define a complex variable: *)
znumber=x+I*y;
(* Define the Split-CReLU function: *)
rePart=Max[Re[znumber],0];
imPart=Max[Im[znumber],0];
splitReLU:=rePart+I imPart;
(* Generate the 3D plot of the specified component: *)
plot1=Plot3D[
component,
{x,-6,6},
{y,-6,6},
(* Plot options: *)
ClippingStyle->None,
AxesLabel->{"Re(z)","Im(z)"},
MeshFunctions->{#3&},
Mesh->15,
MeshStyle->Opacity[.5],
MeshShading->{{Opacity[.3],Blue},{Opacity[.8],Orange}},
Lighting->"Neutral"
600
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
];
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
Split-CReLU: *)
realSplitCReLUPlot=createSplitCReLUPlot[
Re[splitReLU],
"Real Part of split-CReLU(z)"
];
imaginarySplitCReLUPlot=createSplitCReLUPlot[
Im[splitReLU],
"Imaginary Part of split-CReLU(z)"
];
magnitudeSplitCReLUPlot=createSplitCReLUPlot[
Abs[splitReLU],
"Magnitude of split-CReLU(z)"
];
phaseSplitCReLUPlot=createSplitCReLUPlot[
Arg[splitReLU],
"Phase of split-CReLU(z)"
];
601
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
602
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
BoxRatios->{1,1,1},
ImageSize->200
]
Output
(* Define a function to create the plots for different components of the Split-QAM
function: *)
createSplitQAMPlot[component_,label_]:=Module[
{plot1,slice},
603
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
];
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
Split-QAM: *)
realSplitQAMPlot=createSplitQAMPlot[
Re[SplitQAM],
"Real Part of split-QAM(z)"
];
imaginarySplitQAMPlot=createSplitQAMPlot[
Im[SplitQAM],
"Imaginary Part of split-QAM(z)"
];
magnitudeSplitQAMPlot=createSplitQAMPlot[
Abs[SplitQAM],
"Magnitude of split-QAM(z)"
];
phaseSplitQAMPlot=createSplitQAMPlot[
Arg[SplitQAM],
"Phase of split-QAM(z)"
];
604
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
Manipulate[
Module[
{plot1,slice,x,y},
(* Define a complex variable: *)
znumber=x+I*y;
605
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
];
(* Generate the slice contour plot of the real part of Split-QAM: *)
slice=SliceContourPlot3D[
Re[SplitQAM],
z==0,
{x,-6,6},
{y,-6,6},
{z,-1,1},
(* Plot options: *)
Contours->15,
Axes->False,
PlotPoints->50,
PlotRangePadding->0,
ColorFunction->"Rainbow"
];
Output
606
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
607
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
(* Define a function to create the plots for different components of the Split-
absolute value (Split-AV)=Split-Hard Tanh function: *)
createSplitAVPlot[component_,label_]:=Module[
{plot1,slice},
(* Define a complex variable: *)
znumber=x+I*y;
(* Define the Split-AV Tanh function: *)
rePart=1/2 (Abs[Re[znumber]+1]-Abs[Re[znumber]-1]);
imPart=1/2 (Abs[Im[znumber]+1]-Abs[Im[znumber]-1]);
SplitAV:=rePart+I imPart;
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
Split-AV Tanh: *)
realSplitAVPlot=createSplitAVPlot[
Re[SplitAV],
"Real Part of Split-HardTanh(z)"
];
608
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
imaginarySplitAVPlot=createSplitAVPlot[
Im[SplitAV],
"Imaginary Part of Split-HardTanh(z)"
];
magnitudeSplitAVPlot=createSplitAVPlot[
Abs[SplitAV],
"Magnitude of Split-HardTanh(z)"
];
phaseSplitAVPlot=createSplitAVPlot[
Arg[SplitAV],
"Phase of Split-HardTanh(z)"
];
Output
rePart=1/2 (Abs[Re[z]+1]-Abs[Re[z]-1]);
imPart=1/2 (Abs[Im[z]+1]-Abs[Im[z]-1]);
SplitAV:=rePart+I imPart;
609
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
SplitAV,
{z,-3-3 I,3+3 I},
(* Plot options: *)
PlotRange->All,
AxesLabel->{"Re(z)","Im(z)","SplitHardTanh(z)"},
ColorFunction->"CyclicLogAbsArg",
PlotLegends->Automatic,
BoxRatios->{1,1,1},
ImageSize->270
]
Output
(*Define a function to create the plots for different components of the AFTAF
function*)
createAFTAFPlot[component_,label_]:=Module[
{plot1,slice},
(* Define a complex variable: *)
znumber=x+I*y;
610
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
plot1=Plot3D[
component,
{x,-3,3},
{y,-3,3},
(* Plot options: *)
ClippingStyle->None,
AxesLabel->{"Re(z)","Im(z)"},
MeshFunctions->{#3&},
Mesh->15,
MeshStyle->Opacity[.5],
MeshShading->{{Opacity[.3],Blue},{Opacity[.8],Orange}},
Lighting->"Neutral"
];
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
AFTAF: *)
realAFTAFPlot=createAFTAFPlot[
Re[AFTAF],
"Real Part of APTF(z)"
];
imaginaryAFTAFPlot=createAFTAFPlot[
Im[AFTAF],
"Imaginary Part of APTF(z)"
];
magnitudeAFTAFPlot=createAFTAFPlot[
Abs[AFTAF],
"Magnitude of APTF(z)"
];
phaseAFTAFPlot=createAFTAFPlot[
611
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Arg[AFTAF],
"Phase of APTF(z)"
];
Output
612
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
(* Define a function to create the plots for different components of the APSF
function: *)
createAPSFPlot[component_,label_]:=Module[
{plot1,slice},
znumber=x+I*y;
a=1;
b=1;
613
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Lighting->"Neutral"
];
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
APSF: *)
realAPSFPlot=createAPSFPlot[
Re[PASF],
"Real Part of APSF"
];
imaginaryAPSFPlot=createAPSFPlot[
Im[PASF],
"Imaginary Part of APSF"
];
magnitudeAPSFPlot=createAPSFPlot[
Abs[PASF],
"Magnitude of APSF"
];
phaseAPSFPlot=createAPSFPlot[
Arg[PASF],
"Phase of APSF"
];
614
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
615
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
PlotLegends->Automatic,
BoxRatios->{1,1,1},
ImageSize->150
]
Output
Manipulate[
PASF:=(b/(a*b+Abs[z]))*z;
Row[
{
ComplexPlot3D[
PASF,
{z,-6-6 I,6+6 I},
PlotRange->All,
AxesLabel->{"Re(z)","Im(z)","APSF"},
ColorFunction->"CyclicLogAbsArg",
PlotLegends->Automatic,
BoxRatios->{1,1,1},
ImageSize->200
],
ComplexPlot[
PASF,
{z,-6-6 I,6+6 I},
PlotRange->All,
ColorFunction->"CyclicLogAbsArg",
PlotLegends->Automatic,
BoxRatios->{1,1,1},
ImageSize->150
]
}
]
,
{{a,2,"a"},0.1,5,0.1},
{{b,1,"b"},0.1,5,0.1}
]
616
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
(* Define a function to create the plots for different components of the complex
cardioid function: *)
createCardioidPlot[component_,label_]:=Module[
{plot1,slice},
(* Generate the 3D plot of the specified component: *)
plot1=Plot3D[
component,
{x,-6,6},
{y,-6,6},
ClippingStyle->None,
AxesLabel->{"Re(z)","Im(z)"},
MeshFunctions->{#3&},
Mesh->15,
MeshStyle->Opacity[.5],
MeshShading->{{Opacity[.3],Blue},{Opacity[.8],Orange}},
Lighting->"Neutral"
];
617
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
{y,-6,6},
{z,-1,1},
Contours->15,
Axes->False,
PlotPoints->50,
PlotRangePadding->0,
ColorFunction->"Rainbow"
];
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
the complex cardioid function: *)
realCardioidPlot=createCardioidPlot[
Re[cCardioid],
"Real Part of Complex Cardioid"
];
imaginaryCardioidPlot=createCardioidPlot[
Im[cCardioid],
"Imaginary Part of Complex Cardioid"
];
magnitudeCardioidPlot=createCardioidPlot[
Abs[cCardioid],
"Magnitude of Complex Cardioid"
];
phaseCardioidPlot=createCardioidPlot[
Arg[cCardioid],
"Phase of Complex Cardioid"
];
(* Display all four plots together in a list: *)
{realCardioidPlot,imaginaryCardioidPlot,magnitudeCardioidPlot,phaseCardioidPlot}
Output
618
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
619
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
(* Define a function to create the plots for different components of the modReLU
function: *)
createModReLUPlot[component_,label_]:=Module[
{plot1,slice},
(* Generate the 3D plot of the specified component: *)
plot1=Plot3D[
component,
{x,-2,2},
{y,-2,2},
(* Plot options: *)
ClippingStyle->None,
AxesLabel->{"Re(z)","Im(z)"},
MeshFunctions->{#3&},
Mesh->15,
MeshStyle->Opacity[.5],
MeshShading->{{Opacity[.3],Blue},{Opacity[.8],Orange}},
Lighting->"Neutral"
];
620
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
slice,
(* Plot options: *)
PlotRange->All,
PlotLabel->label,
BoxRatios->{1,1,1},
FaceGrids->{Back,Left},
ImageSize->200
]
]
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
modReLU(z): *)
realModReLUPlot=createModReLUPlot[
Re[modReLU],
"Real Part of modReLU(z)"
];
imaginaryModReLUPlot=createModReLUPlot[
Im[modReLU],
"Imaginary Part of modReLU(z)"
];
magnitudeModReLUPlot=createModReLUPlot[
Abs[modReLU],
"Magnitude of modReLU(z)"
];
phaseModReLUPlot=createModReLUPlot[
Arg[modReLU],
"Phase of modReLU(z)"
];
(* Display all four plots together in a list: *)
{realModReLUPlot,imaginaryModReLUPlot,magnitudeModReLUPlot,phaseModReLUPlot}
Output
621
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
622
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
Output
623
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
PlotLegends->Automatic,
BoxRatios->{1,1,1},
ImageSize->200
];
(* Generate a 2D complex plot of the complex modReLU function over a specified
complex range: *)
plot2D=ComplexPlot[
modReLU,
{z,-6-6 I,6+6 I},
(* Plot options: *)
PlotRange->All,
ColorFunction->"CyclicLogAbsArg",
PlotLegends->Automatic,
BoxRatios->{1,1,1},
ImageSize->150
];
{plot3D,plot2D}
]
(* Create an interactive Manipulate environment to adjust the parameter b: *)
Manipulate[
Module[
{plots},
plots=createComplexPlots[b];
Column[plots]],
{{b,-0.7},-3,3,0.1,Appearance->"Labeled"},
ControlPlacement->Top
]
Output
624
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
(* Define a function to create the plots for different components of the tanh
function: *)
createTanhPlot[component_,label_]:=Module[
{plot1,slice},
(* Generate the 3D plot of the specified component: *)
plot1=Plot3D[
component,
{x,-3,3},
{y,-3,3},
(* Plot options: *)
ClippingStyle->None,
AxesLabel->{"Re(z)","Im(z)"},
MeshFunctions->{#3&},
Mesh->15,
MeshStyle->Opacity[.5],
MeshShading->{{Opacity[.3],Blue},{Opacity[.8],Orange}},
Lighting->"Neutral"
];
625
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
]
]
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
tanh(z): *)
realTanhPlot=createTanhPlot[
Re[tanhz],
"Real Part of Tanh(z)"
];
imaginaryTanhPlot=createTanhPlot[
Im[tanhz],
"Imaginary Part of Tanh(z)"
];
magnitudeTanhPlot=createTanhPlot[
Abs[tanhz],
"Magnitude of Tanh(z)"
];
phaseTanhPlot=createTanhPlot[
Arg[tanhz],
"Phase of Tanh(z)"
];
Output
626
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
627
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
628
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
629
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
630
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Show[
plot1,
slice,
(* Plot options: *)
PlotRange->All,
PlotLabel->label,
BoxRatios->{1,1,1},
FaceGrids->{Back,Left},
ImageSize->200
]
]
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
Exp(z): *)
realPlot=createPlot[
Re[expz],
"Real Part of FCExpExp(z)"
];
imaginaryPlot=createPlot[
Im[expz],
"Imaginary Part of FCExp(z)"
];
magnitudePlot=createPlot[
Abs[expz],
"Magnitude of FCExp(z)"
];
phasePlot=createPlot[
Arg[expz],
"Phase of FCExpExp(z)"
];
(* Display all four plots: *)
{realPlot,imaginaryPlot,magnitudePlot,phasePlot}
Output
631
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
632
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
{
{znumber,Re[znumber]>0&&Im[znumber]>0},
{0,True}
}
]
(* Generate the plots for the real part, imaginary part, magnitude, and phase of
zReLU: *)
realzReLU=createPlot[Re,"Real Part of zReLU(z)"];
imaginaryzReLU=createPlot[Im,"Imaginary Part of zReLU(z)"];
magnitudezReLU=createPlot[Abs,"Magnitude of zReLU(z)"];
phasezReLU=createPlot[Arg,"Phase of zReLU(z)"];
633
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
634
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
635
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Manipulate[
{
(* Define the activation functions using Piecewise: *)
(* Define the σzPReLU activation function: *)
σzPReLU:=Piecewise[
{
{z,Re[z]>0&&Im[z]>0},
{α z,True}
}
];
636
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
637
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Axes->False,
PlotPoints->50,
PlotRangePadding->0,
ColorFunction->"Rainbow"
];
638
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
639
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
Output
640
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
641
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
642
CHAPTER 10 COMPLEX VALUED NEURAL NETWORKS
643
References
References
[1] M. M. Hammad, "Statistics for Machine Learning with Mathematica Applications", in arXiv, 2023. doi:
10.48550/arXiv.2310.00004. [Online]. Available: [Link]
[2] M. M. Hammad, "Artificial Neural Network and Deep Learning: Fundamentals and Theory", 2024. doi:
10.13140/RG.2.2.18262.66889. [Online]. Available: [Link]
[3] W. Mendenhall, B. M. Beaver, and R. J. Beaver, "Introduction to Probability and Statistics", 15th ed., New
Delhi: Cengage Learning, 2019.
[4] S. C. Gupta and V. K. Kapoor, "Fundamentals of Mathematical Statistics", Sultan Chand & Sons, 2000.
[5] M. R. Spiegel, "Schaum's Outline of Theory and Problems of Statistics", 2nd ed., McGraw-Hill, 1989.
[6] R. Hogg, J. McKean, and A. Craig, "Introduction to Mathematical Statistics", 7th ed., Pearson, 2012.
[7] D. C. Montgomery and G. C. Runger, "Applied Statistics and Probability for Engineers", 7th ed., Wiley, 2020.
[8] S. M. Ross, "Introduction to Probability and Statistics for Engineers and Scientists", 6th ed., Academic Press,
2020.
[9] K. J. Hastings, "Introduction to Probability with Mathematica", 2nd ed., Chapman and Hall/CRC, 2009.
[10] H. Ruskeepaa, "Mathematica Navigator: Mathematics, Statistics and Graphics", 3rd ed., Academic Press, 2009.
[11] M. M. Hammad and M. M. Yahia, "Mathematics for Machine Learning and Data Science: Optimization with
Mathematica Applications", in arXiv, 2023. doi: 10.48550/arXiv.2302.05964. [Online]. Available:
[Link]
[12] C. P. Simon and L. Blume, "Mathematics for Economists", New York: W. W. Norton & Co., 1994.
[13] J. Lu, "Numerical Matrix Decomposition", in arXiv, 2021. doi: 10.48550/arXiv.2107.02579. [Online].
Available: [Link]
[14] T. Parr and J. Howard, "The Matrix Calculus You Need for Deep Learning", in arXiv, 2018. doi:
10.48550/arXiv.1802.01528. [Online]. Available: [Link]
[15] C. C. Aggarwal, "Linear Algebra and Optimization for Machine Learning: A Textbook", Springer, 2020.
[16] E. K. P. Chong and S. H. Zak, "An Introduction to Optimization", 4th ed., Hoboken, New Jersey: Wiley, 2013.
[17] M. A. Bhatti, "Practical Optimization Methods: With Mathematica® Applications", New York: Springer
Verlag, 2013.
[18] A. Gilat and V. Subramaniam, "Numerical Methods for Engineers and Scientists: An Introduction with
Applications Using MATLAB", 3rd ed., Wiley, 2013.
[20] D. G. Luenberger and Y. Ye, "Linear and Nonlinear Programming", New York: Springer, 2008.
[21] S. Nayak, "Fundamentals of Optimization Techniques with Algorithms", Academic Press, 2020.
[22] K. Deb, "Optimization for Engineering Design: Algorithms and Examples", New Delhi: Prentice-Hall of India,
2004.
644
References
[23] G. V. Reklaitis, A. Ravindran, and K. M. Ragsdell, "Engineering Optimization: Methods and Applications",
New York: Wiley, 1983.
[24] M. M. Hammad, "Deep Learning Activation Functions: Fixed-Shape, Parametric, Adaptive, Stochastic,
Miscellaneous, Non-Standard, Ensemble", in: arXiv, 2024. doi: 10.48550/arXiv.2407.11090. [Online]. Available:
[Link]
[25] I. Goodfellow, Y. Bengio, and A. Courville, "Deep Learning", MIT Press, 2016.
[27] T. Hastie, R. Tibshirani, and J. Friedman, "The Elements of Statistical Learning: Data Mining, Inference, and
Prediction", 2nd ed., Springer, 2008. doi: 10.1007/978-0-387-84858-7. [Online]. Available:
[Link]
[28] J. Patterson and A. Gibson, "Deep Learning: A Practitioner’s Approach", O’Reilly Media, 2017.
[29] U. Michelucci, "Applied Deep Learning: A Case-Based Approach to Understanding Deep Neural Networks",
Apress, 2018.
[30] J. Krohn, G. Beyleveld, and A. Bassens, "Deep Learning Illustrated: A Visual, Interactive Guide to Artificial
Intelligence", Addison-Wesley Professional, 2019.
[32] A. Géron, "Hands-On Machine Learning with Scikit-Learn, Keras, and TensorFlow: Concepts, Tools, and
Techniques to Build Intelligent Systems", O’Reilly Media, 2019.
[33] K. Chaudhury, "Math and Architectures of Deep Learning", Manning Publications, 2021.
[34] E. Raff, "Inside Deep Learning: Math, Algorithms, Models", Manning Publications, 2022.
[35] N. Buduma, N. Buduma, and J. Papa, "Fundamentals of Deep Learning: Designing Next-Generation Machine
Intelligence Algorithms", O'Reilly Media, 2022.
[36] C. M. Bishop and H. Bishop, "Deep Learning Foundations and Concepts", Springer, 2023.
[37] C. C. Aggarwal, "Neural Networks and Deep Learning: A Textbook", Springer, 2023. doi: 10.1007/978-3-031-
29642-0. [Online]. Available: [Link]
[38] S. J. D. Prince, Understanding Deep Learning, Cambridge, MA: MIT Press, 2023.
[39] M. M. Hammad, "Comprehensive Survey of Complex-Valued Neural Networks: Insights into Backpropagation
and Activation Functions", in: arXiv, 2024. doi: 10.48550/arXiv.2407.19258. [Online]. Available:
[Link]
[41] C. Elliott, "The simple essence of automatic differentiation", in Proceedings of the ACM on Programming
Languages, vol. 2, no. 70, pp. 1, 2018. doi: 10.1145/3236765. [Online]. Available: [Link]
[42] C. C. Margossian, "A review of automatic differentiation and its efficient implementation", in WIREs Data
Mining and Knowledge Discovery, vol. 9, no. 4, 2018. doi: 10.1002/widm.1305. [Online]. Available:
[Link]
645
References
[43] A. Paszke, S. Gross, S. Chintala, G. Chanan, E. Yang, Z. DeVito, Z. Lin, A. Desmaison, L. Antiga, and A.
Lerer, "Automatic differentiation in PyTorch", in NIPS 2017 Workshop Autodiff, Tech. Rep., 2017. [Online].
Available: [Link]
[45] K. Hornik, M. Stinchcombe, and H. White, "Multilayer feedforward networks are universal approximators", in
Neural Networks, vol. 2, no. 5, pp. 359, 1989. doi: 10.1016/0893-6080(89)90020-8. [Online]. Available:
[Link]
[46] A. Pinkus, "Approximation theory of the MLP model in neural networks", in Acta Numerica, vol. 8, pp. 143,
1999. doi: 10.1017/S0962492900002919. [Online]. Available: [Link]
[47] X. Glorot and Y. Bengio, "Understanding the difficulty of training deep feedforward neural networks", in
Proceedings of the Thirteenth International Conference on Artificial Intelligence and Statistics (PMLR), vol. 9, pp.
249, 2010. [Online]. Available: [Link]
[48] K. He, X. Zhang, S. Ren, and J. Sun, "Delving deep into rectifiers: Surpassing human-level performance on
ImageNet classification", in Proceedings of the IEEE International Conference on Computer Vision (ICCV), pp.
1026, 2015. [Online]. Available:
[Link]
[49] S. K. Kumar, "On weight initialization in deep neural networks", in arXiv, 2017. doi:
10.48550/arXiv.1704.08863. [Online]. Available: [Link]
[50] W. Cao, X. Wang, Z. Ming, and J. Gao, "A review on neural networks with random weights", in
Neurocomputing, vol. 275, pp. 278, 2018. doi: 10.1016/[Link].2017.08.040. [Online]. Available:
[Link]
[51] W. Boulila, M. Driss, M. Al-Sarem, F. Saeed, and M. Krichen, "Weight initialization techniques for deep
learning algorithms in remote sensing: Recent trends and future perspectives", in F. Saeed, T. Al-Hadhrami, E.
Mohammed, and M. Al-Sarem, Eds., Advances on Smart and Soft Computing: vol. 1399 of Advances in Intelligent
Systems and Computing (AISC), Springer, Singapore, pp. 477, 2022. doi: 10.1007/978-981-16-5559-3_39. [Online].
Available: [Link]
[52] M. V. Narkhede, P. P. Bartakke, and M. S. Sutaone, "A review on weight initialization strategies for neural
networks", in Artificial Intelligence Review, vol. 55, pp. 291, 2022. doi: 10.1007/s10462-021-10033-z. [Online].
Available: [Link]
[53] Y. LeCun, L. Bottou, G. B. Orr, and K. R. Müller, "Efficient backprop", in G. B. Orr and K. R. Müller, Eds.,
Neural Networks: Tricks of the Trade: vol. 1524 of Lecture Notes in Computer Science (LNCS), Springer, Berlin,
Heidelberg, 1998. doi: 10.1007/3-540-49430-8_2. [Online]. Available: [Link]
[54] N. N. Schraudolph, "Centering neural network gradient factor", in G. B. Orr and K. R. Müller, Eds., Neural
Networks: Tricks of the Trade: vol. 1524 of Lecture Notes in Computer Science (LNCS), Springer, Berlin,
Heidelberg, pp. 207, 1998. doi: 10.1007/3-540-49430-8_11. [Online]. Available: [Link]
49430-8_11
[55] Reprint of: Mahalanobis, P.C. (1936) "On the Generalised Distance in Statistics", in Sankhya A, vol. 80, pp. 1,
2018. doi: 10.1007/s13171-019-00164-5. [Online]. Available: [Link]
[56] X. D. Zhang, "A Matrix Algebra Approach to Artificial Intelligence", Springer, Singapore, 2020. doi:
10.1007/978-981-15-2770-8. [Online]. Available: [Link]
646
References
[58] B. S. S. Mohan and C. C. Sekhar, "Class-specific Mahalanobis distance metric learning for biological image
classification", in A. Campilho and M. Kamel, Eds., Image Analysis and Recognition: 9th International Conference,
ICIAR-2012: vol. 7325 of Lecture Notes in Computer Science (LNCS), Springer, Berlin, Heidelberg. doi:
10.1007/978-3-642-31298-4_29. [Online]. Available: [Link]
[59] R. De Maesschalck, D. Jouan-Rimbaud, and D. L. Massart, "The Mahalanobis distance", in Chemometrics and
Intelligent Laboratory Systems, vol. 50, no. 1, pp. 1, 2000. doi: 10.1016/S0169-7439(99)00047-7. [Online].
Available: [Link]
[60] G. Martos, A. Muñoz, and J. González, "On the generalization of the Mahalanobis distance", in J. Ruiz-
Shulcloper and G. S. di Baja, Eds., Progress in Pattern Recognition, Image Analysis, Computer Vision, and
Applications, Lecture Notes in Computer Science (LNCS), vol. 8258, pp. 125, Springer, Berlin, Heidelberg, 2013.
doi: 10.1007/978-3-642-41822-8_16. [Online]. Available: [Link]
[61] L. Novák and M. Vořechovský, "Generalization of coloring linear transformation", in Transactions of the VSB -
Technical University of Ostrava, Civil Engineering Series, vol. 18, no. 2, pp. 31, 2018. doi: 10.31490/tces-2018-
0013. [Online]. Available: [Link]
[62] S. Ioffe and C. Szegedy, "Batch normalization: Accelerating deep network training by reducing internal
covariate shift", in Proceedings of the 32nd International Conference on Machine Learning (PMLR), vol. 37, pp.
448, 2015. [Online]. Available: [Link]
[63] J. L. Ba, J. R. Kiros, and G. E. Hinton, "Layer normalization", in arXiv. doi: 10.48550/arXiv.1607.06450.
[Online]. Available: [Link]
[64] J. Konar, P. Khandelwal, and R. Tripathi, "Comparison of various learning rate scheduling techniques on
convolutional neural network", in IEEE International Students' Conference on Electrical, Electronics and Computer
Science (SCEECS), pp. 1, 2020. doi: 10.1109/SCEECS48394.2020.94. [Online]. Available:
[Link]
[65] S. Biswas and S. Dey, "Relative learning rate adaptation on loss feedback", in TechRxiv, 2023. doi:
10.36227/techrxiv.21980120.v1. [Online]. Available:
[Link]
[68] S. Li, L. Guo, and J. Liu, "Towards East Asian facial expression recognition in the real world: A new database
and deep recognition baseline", in Sensors, vol. 22, no. 21, pp. 8089, 2022. doi: 10.3390/s22218089. [Online].
Available: [Link]
[69] P. Mishra and K. Sarawadekar, "Polynomial learning rate policy with warm restart for deep neural network", in
IEEE Region 10 Conference (TENCON), pp. 2087, 2019. doi: 10.1109/TENCON.2019.8929465. [Online].
Available: [Link]
[70] W. Liu, A. Rabinovich, and A. C. Berg, "Parsenet: Looking wider to see better", in arXiv, 2015. doi:
10.48550/arXiv.1506.04579. [Online]. Available: [Link]
647
References
[71] Y. Dauphin, H. de Vries, and Y. Bengio, "Equilibrated adaptive learning rates for non-convex optimization", in
Advances in Neural Information Processing Systems, vol. 28, pp. 1504, 2015. [Online]. Available:
[Link]
[72] L. N. Smith, "Cyclical learning rates for training neural networks", in IEEE Winter Conference on Applications
of Computer Vision (WACV), pp. 464, 2017. doi: 10.1109/WACV.2017.58. [Online]. Available:
[Link]
[73] I. Loshchilov and F. Hutter, "SGDR: Stochastic gradient descent with warm restarts", in arXiv, 2016. doi:
10.48550/arXiv.1608.03983. [Online]. Available: [Link]
[74] A. Gotmare, N. S. Keskar, C. Xiong, and R. Socher, "A closer look at deep learning heuristics: Learning rate
restarts, warmup and distillation", in arXiv, 2018. doi: 10.48550/arXiv.1810.13243. [Online]. Available:
[Link]
[75] W. An, H. Wang, Y. Zhang, and Q. Dai, "Exponential decay sine wave learning rate for fast deep neural
network training", in IEEE Visual Communications and Image Processing (VCIP), pp. 1, 2017. doi:
10.1109/VCIP.2017.8305126. [Online]. Available: [Link]
[76] B. T. Polya, "Some methods of speeding up the convergence of iteration methods", in USSR Computational
Mathematics and Mathematical Physics, vol. 4, no. 5, pp. 1, 1964. doi: 10.1016/0041-5553(64)90137-5. [Online].
Available: [Link]
[77] I. Sutskever, J. Martens, G. Dahl, and G. Hinton, "On the importance of initialization and momentum in deep
learning", in Proceedings of the 30th International Conference on Machine Learning (PMLR), vol. 28, no. 3, pp.
1139, 2013. [Online]. Available: [Link]
[78] Y. E. Nesterov, "A method of solving a convex programming problem with convergence rate O(1/k^2)", in J.
Dokl. Akad. Nauk SSSR, vol. 269, pp. 543, 1983. [Online]. Available: [Link]
[79] Y. Nesterov, "Introductory Lectures on Convex Optimization: A Basic Course", Springer, 2004.
[80] A. Mustapha, L. Mohamed, and K. Ali, "Comparative study of optimization techniques in deep learning:
Application in the ophthalmology field", in Journal of Physics: Conference Series, vol. 1743, no. 1, 2021. doi:
10.1088/1742-6596/1743/1/012002. [Online]. Available: [Link]
[81] D. Soydaner, "A comparison of optimization algorithms for deep learning", in International Journal of Pattern
Recognition and Artificial Intelligence, vol. 34, no. 13, pp. 2052013, 2020. doi: 10.1142/S0218001420520138.
[Online]. Available: [Link]
[82] M. J. Kochenderfer and T. A. Wheeler, "Algorithms for Optimization", MIT Press, 2019.
[83] S. Santra, J. W. Hsieh, and C. F. Lin, "Gradient descent effects on differential neural architecture search: A
survey", in IEEE Access, vol. 9, pp. 89602, 2021. doi: 10.1109/ACCESS.2021.3090918. [Online]. Available:
[Link]
[84] R. A. Jacobs, "Increased rates of convergence through learning rate adaptation", in Neural Networks, vol. 1, no.
4, pp. 295, 1988. doi: 10.1016/0893-6080(88)90003-2. [Online]. Available: [Link]
6080(88)90003-2
[85] J. Duchi, E. Hazan, and Y. Singer, "Adaptive subgradient methods for online learning and stochastic
optimization", in Journal of Machine Learning Research, vol. 12, no.61, pp. 2121, 2011. [Online]. Available:
[Link]
[86] G. Hinton, "Neural networks for machine learning", Coursera, video lectures, 2012.
648
References
[87] M. D. Zeiler, "Adadelta: An adaptive learning rate method", in arXiv, 2012. doi: 10.48550/arXiv.1212.5701.
[Online]. Available: [Link]
[88] D. P. Kingma and J. Ba, "Adam: A method for stochastic optimization", in arXiv, 2014. doi:
10.48550/arXiv.1412.6980. [Online]. Available: [Link]
[89] T. Dozat, "Incorporating Nesterov momentum into Adam", in International Conference on Learning
Representations (ICLR), Workshop Track, pp. 1, 2016. [Online]. Available:
[Link]
[90] S. J. Reddi, S. Kale, and S. Kumar, "On the convergence of Adam and beyond", in arXiv, 2019. doi:
10.48550/arXiv.1904.09237. [Online]. Available: [Link]
[91] A. Antoniou and W. S. Lu, "Practical Optimization: Algorithms and Engineering Applications", New York:
Springer, 2021.
[93] M. R. Hestenes and E. L. Stiefel, "Methods of conjugate gradients for solving linear systems", in J. Res. Natl.
Bur. Stand., vol. 49, pp. 409, 1952. [Online]. Available: [Link]
[94] D. Chicco and G. Jurman, "The advantages of the Matthews correlation coefficient (MCC) over F1 score and
accuracy in binary classification evaluation", in BMC Genomics, vol. 21, no. 6, 2020. doi: 10.1186/s12864-019-
6413-7. [Online]. Available: [Link]
[95] D. Chicco, N. Toetsch, and G. Jurman, "The Matthews correlation coefficient (MCC) is more reliable than
balanced accuracy, bookmaker informedness, and markedness in two-class confusion matrix evaluation", in BioData
Mining, vol. 14, no. 13, 2021. doi: 10.1186/s13040-021-00244-z. [Online]. Available:
[Link]
[96] T. Fawcett, "An introduction to ROC analysis", in Pattern Recognition Letters, vol. 27, no. 8, pp. 861, 2006.
doi: 10.1016/[Link].2005.10.010. [Online]. Available: [Link]
[97] D. M. W. Powers, "Evaluation: From precision, recall and F-measure to ROC, informedness, markedness and
correlation", in arXiv, 2020. doi: 10.48550/arXiv.2010.16061. [Online]. Available:
[Link]
[98] F. Provost and T. Fawcett, "Data Science for Business: What You Need to Know about Data Mining and Data-
Analytic Thinking", O'Reilly Media, Inc., 2013.
[99] A. Tharwat, "Classification assessment methods", in Applied Computing and Informatics, vol. 17, no. 1, pp.
168, 2021. doi: 10.1016/[Link].2018.08.003. [Online]. Available: [Link]
[100] J. Bergstra and Y. Bengio, "Random search for hyper-parameter optimization", in Journal of Machine
Learning Research, vol. 13, no. 10, pp. 281, 2012. [Online]. Available: [Link]
[101] J. Bergstra, R. Bardenet, Y. Bengio, and B. Kégl, "Algorithms for hyper-parameter optimization", in Advances
in Neural Information Processing Systems (NIPS), vol. 24, pp. 2546, 2011. [Online]. Available:
[Link]
[102] L. Zahedi and F. G. Mohammad, "Search algorithms for automated hyper-parameter tuning", in arXiv, 2021.
doi: 10.48550/arXiv.2104.14677. [Online]. Available: [Link]
[103] H.-C. Kim and M.-J. Kang, "Comparison of hyper-parameter optimization methods for deep neural networks",
in Journal of IKEEE, vol. 24, no. 4, pp. 969, 2020. doi: 10.7471/ikeee.2020.24.4.969. [Online]. Available:
[Link]
649
References
[104] D. A. Anggoro and S. S. Mukti, "Performance comparison of grid search and random search methods for
hyperparameter tuning in extreme gradient boosting algorithm to predict chronic kidney failure", in International
Journal of Intelligent Engineering and Systems, vol. 14, pp. 198, 2021. [Online]. Available: [Link]
content/uploads/2021/10/[Link]
[105] R. Hossain and D. Timmer, "Machine learning model optimization with hyper parameter tuning approach", in
Global Journal of Computer Science and Technology, vol. 21 (D2), pp. 7, 2021. [Online]. Available:
[Link]
[106] H. Alibrahim and S. A. Ludwig, "Hyperparameter optimization: Comparing genetic algorithm against grid
search and bayesian optimization", in IEEE Congress on Evolutionary Computation (CEC), pp. 1551, 2021. doi:
10.1109/CEC45853.2021.9504761. [Online]. Available: [Link]
[107] A. Nugroho and H. Suhartanto, "Hyper-parameter tuning based on random search for densenet optimization",
in 7th International Conference on Information Technology, Computer, and Electrical Engineering (ICITACEE),
pp. 96, 2020. doi: 10.1109/ICITACEE50144.2020.9239164. [Online]. Available:
[Link]
[108] B. H. Shekar and G. Dagnew, "Grid search-based hyperparameter tuning and classification of microarray
cancer data", in Second International Conference on Advanced Computational and Communication Paradigms
(ICACCP), pp. 1, 2019. doi: 10.1109/ICACCP.2019.8882943. [Online]. Available:
[Link]
[110] C. K. Williams and C. E. Rasmussen, "Gaussian Processes for Machine Learning", MIT Press, 2006.
[111] R. B. Gramacy, "Surrogates: Gaussian Process Modeling, Design, and Optimization for the Applied
Sciences", 1st ed., New York: Chapman and Hall/CRC, 2020.
[112] E. Brochu, V. M. Cora, and N. de Freitas, "A tutorial on Bayesian optimization of expensive cost functions,
with application to active user modeling and hierarchical reinforcement learning", in arXiv, 2010. doi:
10.48550/arXiv.1012.2599. [Online]. Available: [Link]
[114] P. I. Frazier, "A tutorial on Bayesian optimization", in arXiv, 2018. doi: 10.48550/arXiv.1807.02811. [Online].
Available: [Link]
[115] A. A. Pawar and U. Warbhe, "Optimizing Bayesian acquisition functions in Gaussian processes", in arXiv,
2021. doi: 10.48550/arXiv.2111.04930. [Online]. Available: [Link]
[116] G. D. Ath, R. M. Everson, A. A. M. Rahat, and J. E. Fieldsend, "Greed is good: Exploration and exploitation
trade-offs in Bayesian optimisation", in ACM Transactions on Evolutionary Learning and Optimization, vol. 1, no.
1, pp. 1, 2021. doi: 10.1145/3425501. [Online]. Available: [Link]
[117] D. D. Cox and S. John, "A statistical method for global optimization", in IEEE International Conference on
Systems, Man, and Cybernetics, vol. 2, pp. 1241, 1992. doi: 10.1109/ICSMC.1992.271617. [Online]. Available:
[Link]
[118] C. Bian, X. Wang, C. Liu, X. Xie, and L. Haitao, "Impact of exploration-exploitation trade-off on UCB-based
Bayesian optimization", in IOP Conference Series: Materials Science and Engineering, vol. 1081, pp. 012023,
2021. doi: 10.1088/1757-899X/1081/1/012023. [Online]. Available: [Link]
899X/1081/1/012023
650
References
[119] U. Noe and D. Husmeier, "On a new improvement-based acquisition function for Bayesian optimization", in
arXiv, 2018. doi: 10.48550/arXiv.1808.06918. [Online]. Available: [Link]
[120] N. Srinivas, A. Krause, S. Kakade, and M. Seeger, "Gaussian process optimization in the bandit setting: No
regret and experimental design", in arXiv, 2010. doi: 10.48550/arXiv.0912.3995. [Online]. Available:
[Link]
[121] H. J. Kushner, "A new method of locating the maximum point of an arbitrary multipeak curve in the presence
of noise", in Journal of Basic Engineering, vol. 86, no. 1, pp. 97, 1964. doi: 10.1115/1.3653121. [Online].
Available: [Link]
[122] A. Klein, S. Falkner, S. Bartels, P. Hennig, and F. Hutter, "Fast Bayesian optimization of machine learning
hyperparameters on large datasets", in Proceedings of the 20th International Conference on Artificial Intelligence
and Statistics (PMLR), vol. 54, pp. 528, 2017. [Online]. Available: [Link]
[123] S. Ament, S. Daulton, D. Eriksson, M. Balandat, and E. Bakshy, "Unexpected improvements to expected
improvement for Bayesian optimization", in Advances in Neural Information Processing Systems (NeurIPS), vol.
36, 2023. [Online]. Available:
[Link]
[124] A. M. Vincent and P. Jidesh, "An improved hyperparameter optimization framework for AutoML systems
using evolutionary algorithms", in Scientific Reports, vol. 13, no. 4737, 2023. doi: 10.1038/s41598-023-32027-3.
[Online]. Available: [Link]
[125] R. Astudillo and P. I. Frazier, "Bayesian optimization of composite functions", in Proceedings of the 36th
International Conference on Machine Learning (PMLR), vol. 97, pp. 354, 2019. [Online]. Available:
[Link]
[126] J. Kong, T. Pourmohamad, and H. K. H. Lee, "Understanding an acquisition function family for Bayesian
optimization", in arXiv, 2023. doi: 10.48550/arXiv.2310.10614. [Online]. Available:
[Link]
[127] F. Bach, R. Jenatton, J. Mairal, and G. Obozinski, "Structured sparsity through convex optimization", in
Statistical Science, vol. 27, no. 4, pp. 450, 2012. doi: 10.1214/12-STS394. [Online]. Available:
[Link]
[128] F. Bach, R. Jenatton, J. Mairal, and G. Obozinski, "Optimization with sparsity-inducing penalties", in
Foundations and Trends in Machine Learning, vol. 4, no. 1, pp. 1, 2012. doi: 10.1561/2200000015. [Online].
Available: [Link]
[129] J. Mairal, F. Bach, and J. Ponce, "Sparse modeling for image and vision processing", in Foundations and
Trends® in Computer Graphics and Vision, vol. 8, no. 2-3, pp. 85, 2014. doi: 10.1561/0600000058. [Online].
Available: [Link]
[130] A. W. Yu, H. Su, and L. Fei-Fei, "Efficient Euclidean projections onto the intersection of norm balls", in
arXiv, 2012. doi: 10.48550/arXiv.1206.4638. [Online]. Available: [Link]
[131] J. Duchi, S. Shalev-Shwartz, Y. Singer, and T. Chandra, "Efficient projections onto the L1-ball for learning in
high dimensions", in the 25th international conference on Machine learning (ICML), pp. 272, 2008. doi:
10.1145/1390156.1390191. [Online]. Available: [Link]
[132] K. Usman, H. Gunawan, and A. B. Suksmono, "Compressive sensing reconstruction algorithm using L1-norm
minimization via L2-norm minimization", in International Journal on Electrical Engineering and Informatics, vol.
10, pp. 37, 2018. doi: 10.15676/ijeei.2018.10.1.3. [Online]. Available: [Link]
[133] J. Songsiri, "Projection onto an L1-norm ball with application to identification of sparse autoregressive
models", in Asean Symposium on Automatic Control (ASAC), 2011.
651
References
[134] S. Rosset and J. Zhu, "Sparse, flexible and efficient modeling using L1 regularization", in Studies in Fuzziness
and Soft Computing, vol. 207, Springer, Berlin, Heidelberg, pp. 375, 2006.
[135] Y. Kim, M. J. Kim, and H. Kim, "Scaled norm-based Euclidean projection for sparse speaker adaptation", in
EURASIP Journal on Advances in Signal Processing, no. 102, 2015. doi: 10.1186/s13634-015-0290-2. [Online].
Available: [Link]
[137] F. Bach, R. Jenatton, J. Mairal, and G. Obozinski, "Convex optimization with sparsity-inducing norms", in S.
Sra, S. Nowozin, and S. J. Wright, Eds., Optimization for Machine Learning, Neural Information Processing Series,
The MIT Press, 2011.
[138] H. Zou and T. Hastie, "Regularization and variable selection via the elastic net", in Journal of the Royal
Statistical Society Series B: Statistical Methodology, vol. 67, no. 2, pp. 301, 2005. doi: 10.1111/j.1467-
9868.2005.00503.x. [Online]. Available: [Link]
[139] L. Breiman, "Bagging predictors", in Machine Learning, vol. 24, pp. 123, 1996. doi: 10.1007/BF00058655.
[Online]. Available: [Link]
[140] N. Srivastava, G. Hinton, A. Krizhevsky, I. Sutskever, and R. Salakhutdinov, "Dropout: a simple way to
prevent neural networks from overfitting", in the journal of machine learning research, vol. 15, pp. 1929, 2014.
652