Animate movement through a Neural Network

It is not very difficult to animate something like this. However, a greater challenge is to keep the computation time semi reasonable. This can be achieved by only making the relevant circles nodes, and drawing the others with a pattern.

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{arrows.meta,patterns.meta}
\tikzdeclarepattern{
name=neurons,
type=uncolored,
bounding box={(-1.25mm,-1.25mm) and (1.25mm,1.25mm)},
tile size={(\tikztilesize,\tikztilesize)}, 
parameters={\tikzcircleradius,\tikztilesize}, 
tile transformation={xshift=1.75mm,yshift=1.75mm},
defaults={
radius/.store in=\tikzcircleradius,radius=1mm, 
tile size/.store in=\tikztilesize,tile size=2.5mm,
}, code={
\draw[thin] (0,0) circle[radius=\tikzcircleradius];
} }
\begin{document}
\foreach \Z in {1,...,24}
{\begin{tikzpicture}[font=\sffamily,>={Triangle[angle=45:.1cm 1]},
    circ/.style={circle,draw,inner sep=0pt,minimum size=2mm}]
 \path[pattern=neurons,local bounding box=input] 
     (-3.5,-3.5) rectangle +(7,7);
 \path[pattern=neurons,pattern color=cyan,
    local bounding box=first]  (5,-3) rectangle +(6,6)
    (.25*\Z+5-0.125, 3-0.125)   
          node[circ,thick,black] (first-1-1) {};
 \path foreach \X in {1,...,5}
  {foreach \Y in {1,...,5}       
  {(-3.5+.25 * \X -0.375+0.25*\Z, 3.5-0.25 * \Y+0.125)
   node[circ,red,thick] (input-\X-\Y){}}};
 \path (input.north) node[above]{input neurons}
   (first.north) node[above=1em]{first hidden layer}; 
 \foreach \X in  {1,...,5}
  {\foreach \Y in {1,...,5}
    {\draw[->,blue!50!cyan,shorten <={(\X-1)*0.25cm}]  (input-\X-\Y) to [in=180, out=0] (first-1-1);}}   
\end{tikzpicture}}
\end{document}

NOTE: The pdf version of the result looks good.

enter image description here

However, if one produces an animated gif from this then the circles do not match! I have no idea why the conversion does that. But this means that in order to have a gif, patterns seem to be not optimal. I do not know if this has been noted before...

Here is a code that takes much more time to compile but has not problem with a gif conversion.

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{arrows.meta}
\begin{document}
\foreach \Z in {1,...,24}
{\begin{tikzpicture}[font=\sffamily,>={Triangle[angle=45:.1cm 1]},
    circ/.style={circle,draw,inner sep=0pt,minimum size=2mm}]
  % 
  \draw[local bounding box=input] foreach \Y in {1, 2, ..., 28} {
         foreach \X in {1, 2, ..., 28} {
          (.25 * \X - 28/8-0.25, -0.25 * \Y + 28/8+0.25) 
          circle[radius=1mm]}};
  \draw[local bounding box=first,xshift=8cm,cyan] foreach \Y in {1, 2, ..., 24} {
         foreach \X in {1, 2, ..., 24} {
          (.25 * \X - 24/8-0.25, -0.25 * \Y + 24/8+0.25) 
          circle[radius=1mm]}}
          (.25 * \Z- 24/8-0.25, 24/8)   
          node[circ,thick,black] (first-1-1) {};         
  \path foreach \X in {1,...,5}
  {foreach \Y in {1,...,5}       
  {(.25 * \X - 28/8-0.25+0.25*\Z-0.25, -0.25 * \Y + 28/8+0.25)
   node[circ,red,thick] (input-\X-\Y){}}};
  \path (input.north) node[above]{input neurons}
   (first.north) node[above]{first hidden layer}; 
  \foreach \X in  {1,...,5}
  {\foreach \Y in {1,...,5}
    {\draw[->,blue!50!cyan,shorten <={(\X-1)*0.25cm}]  (input-\X-\Y) to [in=180, out=0] (first-1-1);}}   
\end{tikzpicture}}
\end{document}

enter image description here

ADDENDUM: After having seen Symbol 1's very nice answer I'd like to add that one can get circles very easily with a dash patten. The key ingredient are the keys

dash pattern=on 0mm off 2.5mm,line cap=round,
double distance between line centers=2mm

where 2.5mm is the distance between the circle centers and 2mm is their radius.

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{arrows.meta}

\begin{document}
\foreach \Z in {1,...,24}
{\begin{tikzpicture}[font=\sffamily,>={Triangle[angle=45:.1cm 1]},
    circ/.style={circle,draw,inner sep=0pt,minimum size=2mm}]
 \draw[local bounding box=input,
    dash pattern=on 0mm off 2.5mm,line cap=round,
    double distance between line centers=2mm] foreach \X in {1,...,28}
  {(-3.4cm+1.5\pgflinewidth,3.6cm-0.25*\X*1cm+1.5\pgflinewidth) -- ++ (6.75,0)};

 \draw[local bounding box=first,cyan,
    dash pattern=on 0mm off 2.5mm,line cap=round,
    double distance between line centers=2mm] foreach \X in {1,...,24}
  {(8cm-2.9cm+1.5\pgflinewidth,3.1cm-0.25*\X*1cm+1.5\pgflinewidth) -- ++ (5.75,0)};

 \path
    (.25*\Z+5-0.125, 3-0.125)   
          node[circ,thick,black] (first-1-1) {};
 \path foreach \X in {1,...,5}
  {foreach \Y in {1,...,5}       
  {(-3.5+.25 * \X -0.375+0.25*\Z, 3.5-0.25 * \Y+0.125)
   node[circ,red,thick] (input-\X-\Y){}}};
 \path (input.north) node[above]{input neurons}
   (first.north) node[above=1em]{first hidden layer}; 
 \foreach \X in  {1,...,5}
  {\foreach \Y in {1,...,5}
    {\draw[->,blue!50!cyan,shorten <={(\X-1)*0.25cm}]  (input-\X-\Y) to [in=180, out=0] (first-1-1);}}   
\end{tikzpicture}}
\end{document}

enter image description here

As one can see, there is not offset whatsoever, and the compilation time is very short.


In addition to @Schrödinger's cat's answer, this is meant to be a supplemental material.

If you don't mind having squares instead of circles, there is a way to generate n^2 squares with O(1) code. It uses dash pattern instead of pattern.

\documentclass{article}
    \usepackage{tikz}
\begin{document}
    \begin{tikzpicture}
        \draw[line width=200,dash pattern=on 2 off 2,dash phase=3]
            (-100pt,0)--(100pt,0);
        \draw[line width=200,dash pattern=on 2 off 2,dash phase=3]
            (0,-100pt)--(0,100pt);
        \draw[white,line width=200,dash pattern=on 2 off 6,dash phase=1]
            (0,-100pt)--(0,100pt);
        \draw[white,line width=200,dash pattern=on 2 off 6,dash phase=1]
            (-100pt,0)--(100pt,0);
    \end{tikzpicture}
\end{document}

8-bit circles

\documentclass{article}
    \usepackage{tikz}
\begin{document}
    \begin{tikzpicture}
        \def\verti{(-100pt,0)--(100pt,0)}\def\horiz{(0,-100pt)--(0,100pt)}
        \def\cross{\verti\horiz}
        \clip(-100pt,-100pt)rectangle(100pt,100pt);
        \begin{scope}[every path/.style={line width=200pt},
            blend mode=darken]
            \begin{scope}[blend group=normal]
                \draw[dash pattern=on2off6,dash phase=5]\verti;
                \draw[dash pattern=on2off1on4off1,dash phase=1,white]\horiz;
            \end{scope}
            \begin{scope}[blend group=normal]
                \draw[blend mode=darken]\verti;
                \draw[dash pattern=on4off1on2off1,dash phase=2,white]\cross;
            \end{scope}
            \begin{scope}[blend group=normal]
                \draw[dash pattern=on2off6,dash phase=5]\horiz;
                \draw[dash pattern=on2off1on4off1,dash phase=1,white]\verti;
            \end{scope}
        \end{scope}
    \end{tikzpicture}
\end{document}

octagon

\documentclass{article}
    \usepackage{tikz}
\begin{document}
    \begin{tikzpicture}
        \def\verti{(-100pt,0)--(100pt,0)}\def\horiz{(0,-100pt)--(0,100pt)}
        \def\diago{(-100pt,-100pt)--(100pt,100pt)}
        \def\antid{(-100pt,100pt)--(100pt,-100pt)}
        \clip(-100pt,-100pt)rectangle(100pt,100pt);
        \begin{scope}[every path/.style={line width=300pt},
            blend mode=darken]
            \begin{scope}[blend group=normal]
                \draw[dash pattern=on3off7,dash phase=6.5]\verti;
                \draw[dash pattern=on3off1on5off1,dash phase=1.5,white]\horiz;
            \end{scope}
            \begin{scope}[blend group=normal]
                \draw[dash pattern=on3off11.142135,dash phase=1.5]\diago;
                \draw[dash pattern=on7off1on5.142135off1,dash phase=3.5,
                    white]\antid;
            \end{scope}
            \begin{scope}[blend group=normal]
                \draw[dash pattern=on3off11.142135,dash phase=1.5]\antid;
                \draw[dash pattern=on7off1on5.142135off1,dash phase=3.5,
                    white]\diago;
            \end{scope}
            \begin{scope}[blend group=normal]
                \draw[dash pattern=on3off11.142135,dash phase=8.5710675]\diago;
                \draw[dash pattern=on7off1on5.142135off1,dash phase=10.5710675,
                    white]\antid;
            \end{scope}
            \begin{scope}[blend group=normal]
                \draw[dash pattern=on3off11.142135,dash phase=8.5710675]\antid;
                \draw[dash pattern=on7off1on5.142135off1,dash phase=10.5710675,
                    white]\diago;
            \end{scope}
            \begin{scope}[blend group=normal]
                \draw[dash pattern=on3off7,dash phase=6.5]\horiz;
                \draw[dash pattern=on3off1on5off1,dash phase=1.5,white]\verti;
            \end{scope}
        \end{scope}
    \end{tikzpicture}
\end{document}