13

I'm trying to create a TikZ based version of the following diagram (taken from here), but I don't know how to approach it.

It doesn't need to look exactly like the original, but the basic idea should be preserved. It would especially be great if the paths from X_n to the sum function were straight lines without a "bend" like in the original. That makes a matrix layout difficult to use.

The definition of the output function can be left away.

Could someone point me to an approach that will work in this case, or even create a tikz texample?

Perceptron


Update: I ended up combining the approaches by @m0nhawk and @Toscho and came up with this:

Perceptron in TikZ

Sourcecode is here: https://github.com/dbrgn/blog/blob/master/content/images/2013/3/26/perceptron.tex

5
  • 4
    Please add a minimal working example (MWE) that illustrates your problem. It's no fun to setup a file from scratch. When you post a compilable code, starting with \documentclass{...} and ending with \end{document} with your existing try-out (no matter how insufficient it is), everybody can jump in much easier.
    – percusse
    Mar 26, 2013 at 8:30
  • Approach it the same way you would draw it. Start with the input circles and place a few below each other. Then the wights, and connect them to the circles, etc... Make an attempt and ask a specific question about what part you are having difficulty with. Mar 26, 2013 at 8:37
  • @percusse The problem is that I don't know what approach/tikzlibrary/layout to use. Therefore a MWE would be just a "base skeleton" with the standalone documentclass. PeterGrill: Ok, I could split it up into different questions (e.g. how to align the inputs around the sum function). But maybe there's a layout or library well suited for this problem, that's why I'm asking. Mar 26, 2013 at 8:41
  • 1
    @DaniloBargen That skeleton would be more than enough :) Just spicing up with the required nodes and it would be good to go. You really don't need to go all the way, just to reduce the load on the potential answerers.
    – percusse
    Mar 26, 2013 at 14:30
  • @percusse ok, i'll do that next time :) Mar 26, 2013 at 21:44

6 Answers 6

14

Here is the simple reconstruction. Issues:

  • Left of equations, can easily be added with node.
  • Make inputs and weights with \foreach.
  • Increase the Activation function to be more like the original one.
  • Improve TikZ styles.

Code:

\documentclass[tikz]{standalone}
\usepackage{tikz}
    \usetikzlibrary{positioning}

\tikzset{basic/.style={draw,fill=blue!20,text width=1em,text badly centered}}
\tikzset{input/.style={basic,circle}}
\tikzset{weights/.style={basic,rectangle}}
\tikzset{functions/.style={basic,circle,fill=blue!10}}

\begin{document}
    \begin{tikzpicture}
        \node[functions] (center) {};
        \node[below of=center,font=\scriptsize,text width=4em] {Activation function};
        \draw[thick] (0.5em,0.5em) -- (0,0.5em) -- (0,-0.5em) -- (-0.5em,-0.5em);
        \draw (0em,0.75em) -- (0em,-0.75em);
        \draw (0.75em,0em) -- (-0.75em,0em);
        \node[right of=center] (right) {};
            \path[draw,->] (center) -- (right);
        \node[functions,left=3em of center] (left) {$\sum$};
            \path[draw,->] (left) -- (center);
        \node[weights,left=3em of left] (2) {$w_2$} -- (2) node[input,left of=2] (l2) {$x_2$};
            \path[draw,->] (l2) -- (2);
            \path[draw,->] (2) -- (left);
        \node[below of=2] (dots) {$\vdots$} -- (dots) node[left of=dots] (ldots) {$\vdots$};
        \node[weights,below of=dots] (n) {$w_n$} -- (n) node[input,left of=n] (ln) {$x_n$};
            \path[draw,->] (ln) -- (n);
            \path[draw,->] (n) -- (left);
        \node[weights,above of=2] (1) {$w_1$} -- (1) node[input,left of=1] (l1) {$x_1$};
            \path[draw,->] (l1) -- (1);
            \path[draw,->] (1) -- (left);
        \node[weights,above of=1] (0) {$w_0$} -- (0) node[input,left of=0] (l0) {$1$};
            \path[draw,->] (l0) -- (0);
            \path[draw,->] (0) -- (left);
        \node[below of=ln,font=\scriptsize] {inputs};
        \node[below of=n,font=\scriptsize] {weights};
    \end{tikzpicture}
\end{document}

Picture:

result

3
9

Here a shorter code without positioning, so you can scale the picture.

\documentclass[tikz]{article}
\usepackage{tikz}

\tikzset{basic/.style={draw,fill=blue!50!green!20,
                       text badly centered,minimum width=3em}}
\tikzset{input/.style={basic,circle}}
\tikzset{weights/.style={basic,rectangle,minimum width=2em}}
\tikzset{functions/.style={basic,circle,fill=blue!50!green!20}}
\newcommand{\addsymbol}{\draw[thick] (0.5em,0.5em) -- (0,0.5em) -- 
                        (0,-0.5em) --  (-0.5em,-0.5em)
                        (0em,0.75em) -- (0em,-0.75em)
                        (0.75em,0em) -- (-0.75em,0em);}

\begin{document}
    \begin{tikzpicture}[scale=1.2]
    \foreach \h [count=\hi ] in {$x_n$,$x_2$,$x_1$,$1$}{%
          \node[input] (f\hi) at (0,\hi*2cm-5 cm) {\h};
        }
    \node[functions] (sum) at (4,0) {$\sum$};
    \foreach \h [count=\hi ] in {$w_n$,$w_2$,$w_1$,$w_0$}{%
          \path (f\hi) -- node[weights] (w\hi) {\h} (sum);
          \draw[->] (f\hi) -- (w\hi);
          \draw[->] (w\hi) -- (sum);
        }        
    \node[functions] (step) at (7,0) {};
       \begin{scope}[xshift=7cm,scale=.75]
         \addsymbol
       \end{scope}
    \draw[->] (sum) -- (step);
    \draw[->] (step) -- ++(1,0);
    % Labels
    \node[above=1cm]  at (f4) {inputs};
    \node[above=1cm] at (w4) {weights};
    \end{tikzpicture}
\end{document}

enter image description here

7

With PSTricks but not completed...

enter image description here

\documentclass[preview,border=12pt]{standalone}
\usepackage{pst-node}
\usepackage{amsmath}
\psset
{
    rowsep=4mm,
    colsep=8mm,
    mnodesize=10mm,
    mnode=r,
}
\newcommand{\C}[1]{[mnode=circle,fillstyle=solid,fillcolor=blue!20]$#1$}
\newcommand{\R}[1]{[mnode=r]\psframebox[fillstyle=solid,fillcolor=blue!20]{\parbox{4mm}{\strut\centering$#1$}}}
\def\Symbol{%
\psset{unit=3mm}
\pspicture(-1,-1)(1,1)
    \psset{linewidth=0.4pt}
    \psline(-1,0)(1,0)
    \psline(0,-1)(0,1)
    \psline[linewidth=2\pslinewidth](-0.75,-0.5)(0,-0.5)(0,0.5)(0.75,0.5)
\endpspicture
}
\begin{document}
\offinterlineskip
\begin{psmatrix}
    \C{1}           & \R{w_0}\\
    \C{x_1}         & \R{w_1}\\
    \C{x_2}         & \R{w_2}       & \C{\Sigma}    & [mnode=circle,fillstyle=solid,fillcolor=blue!20,name=symbol]\Symbol   &   [mnode=p]\\
    \vdots          & \vdots\\
    \C{x_n}         & \R{w_n}\\
    \text{inputs}   & \text{weights}
    \psset{arrows=->}
    \ncline{1,1}{1,2}
        \ncline{2,1}{2,2}
            \ncline{3,1}{3,2}
                \ncline{5,1}{5,2}
    \ncdiagg{1,2}{3,3}
        \ncdiagg{2,2}{3,3}
            \ncdiagg{3,2}{3,3}
                \ncdiagg{5,2}{3,3}
    \ncline{3,3}{3,4}
    \ncline{3,4}{3,5}
\end{psmatrix}
\end{document}
1
  • Enough with PSTricks, already! Nah, just kidding... :) Good job!
    – jub0bs
    Mar 26, 2013 at 19:05
4

If I understand you correctly, you want the nodes wn to lie on straight lines from the nodes xn to the node ∑. Then you can do

\usetikzlibrary{calc}
[…]
\node[…](w1) at ($(x1)!0.5!(sum)$) {\(w_n\)};
[…]

or

[…]
\path(x1)--node[…](w1){\(w_n\)}(sum);
[…]
0
3

I modified the solution of @Naphat to make it match the OP requested solution:

\documentclass[tikz]{article}
\usepackage{tikz}

\tikzset{basic/.style={draw,fill=none,
                       text badly centered,minimum width=3em}}
\tikzset{input/.style={basic,circle,minimum width=3.5em}}
\tikzset{weights/.style={basic,rectangle,minimum width=2em}}
\tikzset{functions/.style={basic,circle, minimum width=4em}}
\newcommand{\addaxes}{\draw (0em,1em) -- (0em,-1em)
                            (-1em,0em) -- (1em,0em);}
\newcommand{\relu}{\draw[line width=1.5pt] (-1em,0) -- (0,0)
                                (0,0) -- (0.75em,0.75em);}
\newcommand{\stepfunc}{\draw[line width=1.5pt] (0.65em,0.65em) -- (0,0.65em) 
                                    -- (0,-0.65em) -- (-0.65em,-0.65em);}

\begin{document}
    \begin{tikzpicture}[scale=1.2]
    % Draw input nodes
    \foreach \h [count=\hi ] in {$x_2$,$x_1$,$1$}{%
        \node[input] (f\hi) at (0,\hi*1.5cm-1.5 cm) {\h};
      }
    % Dot dot dot ... x_n
    \node[below=0.62cm] (idots) at (f1) {\vdots};
    \node[input, below=0.62cm] (last_input) at (idots) {$x_n$};
    % Draw summation node
    \node[functions] (sum) at (4,0) {\Huge$\sum$};
    % Draw edges from input nodes to summation node
    \foreach \h [count=\hi ] in {$w_2$,$w_1$,$w_0$}{%
          \path (f\hi) -- node[weights] (w\hi) {\h} (sum);
          \draw[->] (f\hi) -- (w\hi);
          \draw[->] (w\hi) -- (sum);
        }
    % Dot dot dot ... w_n
    \node[below=0.05cm] (wdots) at (w1) {\vdots};
    \node[weights, below=0.45cm] (last_weight) at (wdots) {$w_n$};
    % Add edges for last node and last weight etc
    \path[draw,->] (last_input) -- (last_weight);
    \path[draw,->] (last_weight) -- (sum);
    % Draw node for activation function
    \node[functions] (activation) at (7,0) {};
    % Place activation function in its node
    \begin{scope}[xshift=7cm,scale=1.25]
        \addaxes
        % flexible selection of activation function
        % \relu
        \stepfunc
    \end{scope}
    % Connect sum to activation function
    \draw[->] (sum) -- (activation) node (sum_eq) [midway, below=2cm, scale=1.2] {$\sum\limits_{i=0}^n w_ix_i$} node (sum_activation_midway) [midway, below] {};
    \path[draw,->] (sum_eq) -- (sum_activation_midway);
    \draw[->] (activation) -- ++(3,0) node (perceptron_output) [below=0.2cm, scale=1.2] {$output = \begin{cases}1 & \text{if }\ \sum\limits_{i=0}^n w_ix_i > 0,\\-1 & \text{otherwise}\end{cases}$};
    % Labels
    \node[above=1cm]  at (f3) {Inputs};
    \node[above=1cm] at (w3) {Weights};
    \node[above=1.5cm] at (activation) {Activation Function};
    \end{tikzpicture}
\end{document}

enter image description here

2

I am aware this is an old post, but I'll share what I did in case in becomes useful for others. I liked @m0nhawk's design (with \vdots) and @Alain Matthes' code, so I combined them. I also changed the activation to ReLU, but the code step function is still avilable.

It should be noted that I broke the size "scalability" from @Alain Matthes' code. Instead I use \resizebox to resize the figure.

\documentclass[tikz]{article}
\usepackage{tikz}

\tikzset{basic/.style={draw,fill=none,
                       text badly centered,minimum width=3em}}
\tikzset{input/.style={basic,circle,minimum width=3.5em}}
\tikzset{weights/.style={basic,rectangle,minimum width=2em}}
\tikzset{functions/.style={basic,circle, minimum width=4em}}
\newcommand{\addaxes}{\draw (0em,1em) -- (0em,-1em)
                            (-1em,0em) -- (1em,0em);}
\newcommand{\relu}{\draw[line width=1.5pt] (-1em,0) -- (0,0)
                                (0,0) -- (0.75em,0.75em);}
\newcommand{\stepfunc}{\draw[line width=1.5pt] (0.65em,0.65em) -- (0,0.65em) 
                                    -- (0,-0.65em) -- (-0.65em,-0.65em);}

\begin{document}
    \begin{tikzpicture}[scale=1.2]
    % Draw input nodes
    \foreach \h [count=\hi ] in {$x_2$,$x_1$,$x_0=1$}{%
          \node[input] (f\hi) at (0,\hi*1.25cm-1.5 cm) {\h};
        }
    % Dot dot dot ... x_n
    \node[below=0.62cm] (idots) at (f1) {\vdots};
    \node[input, below=0.62cm] (last_input) at (idots) {$x_n$};
    % Draw summation node
    \node[functions] (sum) at (4,0) {\Huge$\sum$};
    \node[below=0.69cm] at (sum) {$\sum_{i=0}^n w_ix_i$};
    % Draw edges from input nodes to summation node
    \foreach \h [count=\hi ] in {$w_2$,$w_1$,$w_0$}{%
          \path (f\hi) -- node[weights] (w\hi) {\h} (sum);
          \draw[->] (f\hi) -- (w\hi);
          \draw[->] (w\hi) -- (sum);
        }
    % Dot dot dot ... w_n
    \node[below=0.05cm] (wdots) at (w1) {\vdots};
    \node[weights, below=0.45cm] (last_weight) at (wdots) {$w_n$};
    % Add edges for last node and last weight etc
    \path[draw,->] (last_input) -- (last_weight);
    \path[draw,->] (last_weight) -- (sum);
    % Draw node for activation function
    \node[functions] (activation) at (7,0) {};
    % Place activation function in its node
    \begin{scope}[xshift=7cm,scale=1.25]
        \addaxes
        % flexible selection of activation function
        \relu
        % \stepfunc
    \end{scope}
    % Connect sum to relu
    \draw[->] (sum) -- (activation);
    \draw[->] (activation) -- ++(1,0);
    % Labels
    \node[above=1cm]  at (f3) {inputs};
    \node[above=1cm] at (w3) {weights};
    \node[above=1cm] at (activation) {activation function};
    \end{tikzpicture}
\end{document}

Result:

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .