% LTeX: language=en % huffman : draw binary huffman trees with MetaPost/MetaObj % % Originally written by Maxime Chupin , % 2023. % % Distributed under the terms of the GNU free documentation licence: % http://www.gnu.org/licenses/fdl.html % without any invariant section or cover text. \documentclass[english]{ltxdoc} \input{mp-neuralnetwork-preamble.tex} \usepackage[english]{babel} \makeindex[title=Command Index, columns=2] %\lstset{moredelim=*[s][\color{red}\rmfamily\itshape]{<}{>}} %\lstset{moredelim=*[s][\color{blue}\rmfamily\itshape]{<<}{>>}} \begin{document} \title{{\mpneural} : drawing artificial neural networks with \MP and \MO/} \author{Maxime Chupin, \url{notezik@gmail.com}} \date{\today} %% === Page de garde =================================================== \thispagestyle{empty} \begin{tikzpicture}[remember picture, overlay] \node[below right, shift={(-4pt,4pt)}] at (current page.north west) {% \includegraphics{fond.pdf}% }; \end{tikzpicture}% \noindent {\Huge \mpneural}\par\bigskip \noindent {\Large drawing artificial neural networks \\[0.2cm]with \hologo{METAPOST} and \MO/}\\[1cm] \parbox{0.6\textwidth}{ \begin{mplibcode}[mpneural] input mp-neuralnetwork; beginfig(1); framed_output(false); framed_input(false); drawANN("x","n","a","p","b","q","y","m") "circmargin(3pt)"; endfig; \end{mplibcode} }\hfill \parbox{0.5\textwidth}{\Large\raggedleft \textbf{Contributor}\\ Maxime \textsc{Chupin}\\ \url{notezik@gmail.com} } \vfill \begin{center} Version 0.1, 2025, January, 27th \\ \url{https://gitlab.gutenberg-asso.fr/mchupin/mp-neuralnetwork} \end{center} %% == Page de garde ==================================================== \newpage %\maketitle \begin{abstract} This \hologo{METAPOST} package allows to draw artificial neural networks. It is based on the \MO/ package which provides many tools to draw and arrange nodes. \end{abstract} \begin{center} \url{https://gitlab.gutenberg-asso.fr/mchupin/mp-neuralnetwork} \end{center} \tableofcontents \bigskip \begin{tcolorbox}[ arc=0pt,outer arc=0pt, colback=darkred!3, colframe=darkred, breakable, boxsep=0pt,left=5pt,right=5pt,top=5pt,bottom=5pt, bottomtitle = 3pt, toptitle=3pt, boxrule=0pt,bottomrule=0.5pt,toprule=0.5pt, toprule at break = 0pt, bottomrule at break = 0pt,] \itshape This package is in beta version---do not hesitate to report bugs, as well as requests for improvement. \end{tcolorbox} \section{Installation} \mpneural is on \ctan{} and can also be installed via the package manager of your distribution. \begin{center} \url{https://www.ctan.org/pkg/mp-neuralnetwork} \end{center} \subsection{With \TeX live under Linux or macOS} To install \mpneural with \TeX Live, you will have to create the directory \lstinline+texmf+ in your \lstinline+home+. \begin{commandshell} mkdir ~/texmf \end{commandshell} Then, you will have to place the \lstinline+neuralnetwork.mp+ and \lstinline+metaobj-patch.mp+\footnote{Thanks to Denis Roegel, this file define a \texttt{Group} object to group different \MO/ objects. } files in \begin{center} \lstinline+~/texmf/metapost/mp-neuralnetwork/+ \end{center} Once this is done, \mpneural will be loaded with the classic \MP{} input code \begin{mpcode} input mp-neuralnetwork \end{mpcode} \subsection{With Mik\TeX{} and Windows} These two systems are unknown to the author of \mpneural, so we refer you to the Mik\TeX documentation concerning the addition of local packages: \begin{center} \url{http://docs.miktex.org/manual/localadditions.html} \end{center} \subsection{Dependencies} \mpneural depends: \begin{itemize} \item of course on \MP~\cite{ctan-metapost}; \item on the package\package{metaobj}~\cite{ctan-metaobj}; \item if \mpneural is not used with \hologo{LuaLaTeX} and the \package{luamplib} package, on the \package{latexmp} package\cite{ctan-latexmp}; \item and on the package \package{colorbrewer-rgb}~\cite{ctan-metapost-colorbrewer}. \end{itemize} \section{Main Command} The package \mpneural provides one principal command that has two possible invocations. \subsection{Finite network} \commande|drawANN(«name1»,«size1»,«name2»,«size2», etc.)|\smallskip\index{drawANN@\lstinline+drawANN+} Each layer of the network is described by a couple \meta{name} and \meta{size}, where: \begin{description} \item[\meta{name}:] is the names of the layers. It a string, and this is the prefix of each node (for instance \lstinline+"x"+ will produce nodes $x_i$). \item[\meta{size}:] is the size (integer) of the layer (for instance if \meta{size}$=4$, the layer will be composed by nodes $x_1$, $x_2$, $x_3$ and $x_4$). \end{description} Here, a simple example. \begin{ExempleMP} input mp-neuralnetwork beginfig(1); drawANN("x",4,"y",5,"z",1); endfig; \end{ExempleMP} \subsection{Abstract network} You can set variables for the size of each layers with the same command using the string notation for the size instead of an integer. \commande|drawANN(«name1»,«size1»,«name2»,«size2», etc.)|\smallskip\index{drawANN@\lstinline+drawANN+} Each layer of the network is described by a couple \meta{name} and \meta{size}, where: \begin{description} \item[\meta{name}:] is the names of the layers. It a string, and this is the prefix of each node (for instance \lstinline+"x"+ will produce nodes $x_i$). \item[\meta{size}:] is the notation for size (string) of the layer (for instance \lstinline+"p"+, the layer will be composed by nodes $x_1$, $x_2$, $\dots$ and $x_p$). \end{description} Here, a simple example. \begin{ExempleMP} input mp-neuralnetwork beginfig(1); drawANN("x","m","y","n","z","p"); endfig; \end{ExempleMP} The first and the last layers are composed with four nodes, and intern layers with five nodes. \section{Options} \mpneural allows to customize the network representation. If you want to restore default behaviour, you can use the following command. \commande|mpneural_init_values|\smallskip\index{mpneural_init_values@\lstinline+mpneural_init_values+} \subsection{Colors} We can see, in the previous examples, that the nodes are colored. If you do not want them to be colored, use the following command. \commande|colored_layers(«boolean»)|\smallskip\index{colored_layers@\lstinline+colored_layers+} \begin{description} \item[\meta{boolean}:] is a \MP{} boolean (true by default) to choose if we want or not colored layers. \end{description} If the layers are colored, \mpneural{} uses \lstinline+Spectral+ colors defined in \package{colorbrewer-rgb}\footnote{Up to 11 colors. If there are more layers, the colors cycle.}. You can also define colors for each layer using the following command. \commande|set_layer_colors(«layer number1»,«color1»,«layer number 1»,«color1»,etc.)|\smallskip\index{set_layer_colors@\lstinline+set_layer_colors+} \begin{description} \item[\meta{layer number 1}, \meta{color1}:] is a couple with the integer of the layer we want to color with \meta{color1}. \end{description} The rest of layers are set to white by default. For example: \begin{ExempleMP} input mp-neuralnetwork colored_layers(false); beginfig(1); drawANN("x",5,"y",1); endfig; \end{ExempleMP} and \begin{ExempleMP} input mp-neuralnetwork colored_layers(true); set_layer_colors(1,red,3,(0.7,0.7,0.7)); beginfig(1); drawANN("x",5,"y",1,"z",4); endfig; \end{ExempleMP} Connections are colored. The default color is gray (\lstinline+0.4*white+) but you can modify that with the following command. \commande|set_connection_color(«color»)|\smallskip\index{set_connection_color@\lstinline+set_connection_color+} \begin{description} \item[\meta{color}:] is the color for drawing the connections between layers (default \lstinline+0.4*white+). \end{description} \subsection{Annotations} \mpneural provides some tools to annotate the network. However, because we use \MO/ behind the scene, you can always use \MO/ tools to draw above the graph build with \mpneural (see section~\ref{sec:mo}). \subsubsection{Frames} You can add frames around three different blocks: input, output and hidden layers. To draw a frame around these three types of layers (or stop the drawing of theses frames), you can use the following commands. \commande|framed_input(«boolean»)|\smallskip\index{framed_input@\lstinline+framed_input+} \commande|framed_output(«boolean»)|\smallskip\index{framed_output@\lstinline+framed_output+} \commande|framed_hidden(«boolean»)|\smallskip\index{framed_hidden@\lstinline+framed_hidden+} \begin{description} \item[\meta{boolean}:] true or false (default). \end{description} \subsubsection{Positioning nodes} We can adjust the vertical and horizontal distance between nodes with the following commands. \commande|set_vspace(«distance»)|\smallskip\index{set_vspace@\lstinline+set_vspace+} \begin{description} \item[\meta{distance}:] is a numeric (default \lstinline+1.5cm+). \end{description} \commande|set_hspace(«distance»)|\smallskip\index{set_hspace@\lstinline+set_hspace+} \begin{description} \item[\meta{distance}:] is a numeric (default \lstinline+2.2cm+). \end{description} \begin{ExempleMP} input mp-neuralnetwork beginfig(1); set_vspace(2cm); set_hspace(3cm); drawANN("x",5,"u",6,"v",3,"y",2); endfig; \end{ExempleMP} \subsubsection{Labels and sections} First, if you do not want to label the nodes, use the following command to deactivate the function. \commande|show_node_labels(«boolean»)|\smallskip\index{show_node_labels@\lstinline+show_node_labels+} You can also add legends to these part of the network (independently of the frame draw). For that, you can use the following command. \commande|print_legends(«boolean»)|\smallskip\index{print_legends@\lstinline+print_legends+} \begin{description} \item[\meta{boolean}:] true or false (default). \end{description} The default value for the legends of the three parts (input, output, and hidden), are \lstinline+"Input layer"+, \lstinline+"Output layer"+, and \lstinline+"Hidden layer(s)"+. You can modify these string with the following commands. \commande|set_input_legend(«string»)|\smallskip\index{set_input_legend@\lstinline+set_input_legend+} \commande|set_output_legend(«string»)|\smallskip\index{set_output_legend@\lstinline+set_output_legend+} \commande|set_hidden_legend(«string»)|\smallskip\index{set_hidden_legend@\lstinline+set_hidden_legend+} \begin{description} \item[\meta{string}:] is a string for the legend (default are \lstinline+"Input layer"+, \lstinline+"Output layer"+, and \lstinline+"Hidden layer(s)"+). \end{description} \begin{ExempleMP} input mp-neuralnetwork colored_layers(false); beginfig(1); print_legends(true); set_input_legend("Entrées"); set_output_legend("Sortie"); framed_hidden(true); drawANN("x",5,"u",6,"v",8,"y",2); endfig; \end{ExempleMP} You may also want to print the \emph{weights} on the network. To do that, use the following commands. \commande|print_weights(«boolean»)|\smallskip\index{print_weights@\lstinline+print_weights+} By default, weights are denoted by $w$, but you can change that with the following command. \commande|set_weights_notation(«string»)|\smallskip\index{set_weights_notation@\lstinline+set_weights_notation+} \begin{description} \item[\meta{string}:] is a string for the weights (default is \lstinline+"w"+). This is a prefix: for instance, with the default value, the weights are, in math mode, $w_{ij}^{(k)}$ for the $k$-th layer. \end{description} \begin{ExempleMP} input mp-neuralnetwork colored_layers(false); beginfig(1); print_legends(false); print_weights(true); drawANN("x",4,"u",6,"v",5,"y",2); endfig; \end{ExempleMP} You can add labels positioning them with relative coordinates that is $(0,0)$ at bottom left of the bounding box of the complete graph and $(1,1)$ at top right. For that, you can use the following command. \commande|labelANN(«string»)(«xpart»,«ypart») «\MO/ options»|\smallskip\index{labelANN@\lstinline+labelANN+} \begin{description} \item[\meta{string}:] is a string for the label (process by \lstinline+textext+ command). \item[\meta{xpart},\meta{ypart}:] are numeric in the relative coordinates (but can be lower or greater than 0 and 1.). \end{description} This command build a \MO/ box. It is the center of the box that is put at the relative coordinate. Moreover, you can add the \MO/ options at the end to customize the box. \begin{ExempleMP} input mp-neuralnetwork colored_layers(false); beginfig(1); print_legends(false); print_weights(true); drawANN("x",4,"u",6,"v",5,"y",2); labelANN("My fabulous network")(0.5,-0.2) "filled(true)","fillcolor((0.8,0.5,0.5))"; endfig; \end{ExempleMP} \section{With MetaObj}\label{sec:mo} Because \mpneural is built above \MO/~\cite{ctan-metaobj}, the tools of the incredible package are available. The nodes of the network are \MO/ boxes, with names: \begin{itemize} \item with the prefix \texttt{ANN}; \item the instance number of the network (useful if you draw multiple networks); \item an underscore \texttt{\_}; \item the identifier of the layer (specified in the \lstinline+drawANN+ command); \item the number of the node in the layer. \end{itemize} The boxes of weights are named as follows: \begin{itemize} \item with the prefix \texttt{ANN}; \item the instance number of the network (useful if you draw multiple networks); \item an underscore \texttt{\_}; \item \texttt{weights}; \item the number of the left layer. \end{itemize} The boxes of label for input, output and hidden layers are named as follows: \begin{itemize} \item with the prefix \texttt{ANN}; \item the instance number of the network (useful if you draw multiple networks); \item an underscore \texttt{\_}; \item \texttt{input}, \texttt{output} or \texttt{hidden}. \end{itemize} Labels generated by \lstinline+labelANN+ are also \MO/ boxes named as follows: \begin{itemize} \item with the prefix \texttt{ANN}; \item the instance number of the network (useful if you draw multiple networks); \item an underscore \texttt{\_}; \item \texttt{label}; \item then the number of the label. \end{itemize} For example, if you draw the following network: \begin{mpcode} input mp-neuralnetwork beginfig(1); drawANN("x",3,"y",2); endfig; \end{mpcode} The nodes will be named \texttt{ANN1\_x1}, \texttt{ANN1\_x2}, \texttt{ANN1\_x3}, \texttt{ANN1\_y1}, and \texttt{ANN1\_y2}. The weights will be named \texttt{ANN1\_weights1}. Here is a real example (this is the 10th instance of a network drawing in this document). \lstinline+ncline+ is a \MO/ command. \begin{ExempleMP} input mp-neuralnetwork; beginfig(1); print_legends(true); show_node_labels(true); drawANN("x","n","a","p","b","q","y","m") "circmargin(3pt)"; labelANN("Test")(1.3,0.4); labelANN("Test")(0.5,1.1) "framed(false)"; ncline(ANN10_label2)(ANN10_x2)"doubleline(true)","coilwidth(2mm)", "angleA(0)", "linewidth(1pt)"; endfig; \end{ExempleMP} \printbibliography \printindex \end{document}