tikz 내에서 \FPeval로 계산된 \def 변수 사용

tikz 내에서 \FPeval로 계산된 \def 변수 사용

안녕하세요 완전 초보입니다.

신경망을 그리기 위해 일부 tikz 템플릿을 가져와서 레이어 수를 자동으로 변경할 수 있도록 수정하려고 시도했지만 이상한 오류가 발생했습니다.

나는 이 패키지를 사용하고 있는데 그것이 중요한지 전혀 모릅니다

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[czech]{babel}
\usepackage[margin=2cm, a4paper]{geometry}
\usepackage[T1]{fontenc}
\usepackage{fontawesome}
\usepackage{xcolor}
\usepackage{graphicx}
\usepackage{array}
\usepackage[protrusion,expansion]{microtype}
\usepackage{tikz}
\usepackage[nomessages]{fp}

별도의 .sty 파일에 다음 매크로를 생각해냈습니다.

\newcommand{\mln}[3]{
    \def\layersep{#1}
    \def\inpneuroncount{#2}
    \def\hidneuroncount{#3}

    \FPeval{result}{clip((\hidneuroncount-\inpneuroncount)/2)}
    \def\nodeoffset{yshift=\result cm}
    \nodeoffset

    \begin{tikzpicture}[shorten >=1pt,->,draw=black!50, node distance=\layersep]
        \tikzstyle{every pin edge}=[<-,shorten <=3pt]
        \tikzstyle{neuron}=[circle,fill=black!25,minimum size=15pt,inner sep=0pt]
        \tikzstyle{input neuron}=[neuron, fill=green!50];
        \tikzstyle{output neuron}=[neuron, fill=red!50];
        \tikzstyle{hidden neuron}=[neuron, fill=blue!50];
        \tikzstyle{annot} = [text width=4em, text centered]

        % Draw the input layer nodes
        \foreach \name / \y in {1,...,\inpneuroncount}
        % This is the same as writing \foreach \name / \y in {1/1,2/2,3/3,4/4}
            \node[input neuron, pin=left:Input \#\y] (I-\name) at (0,-\y) {};

        % Draw the hidden layer nodes
        \foreach \name / \y in {1,...,\hidneuroncount}
            \path[\nodeoffset]
                node[hidden neuron] (H-\name) at (\layersep,-\y cm) {};

        % Draw the output layer node
        \node[output neuron,pin={[pin edge={->}]right:Output}, right of=H-1] (O) {};

        % Connect every node in the input layer with every node in the
        % hidden layer.
        \foreach \source in {1,...,\inpneuroncount}
            \foreach \dest in {1,...,\hidneuroncount}
                \path (I-\source) edge (H-\dest);

        % Connect every node in the hidden layer with the output layer
        \foreach \source in {1,...,\hidneuroncount}
            \path (H-\source) edge (O);

        % Annotate the layers
        \node[annot,above of=H-1, node distance=1cm] (hl) {Hidden layer};
        \node[annot,left of=hl] {Input layer};
        \node[annot,right of=hl] {Output layer};
    \end{tikzpicture}
    % End of code
}

내가 하려고 하는 것은 은닉층의 yshift를 입력 뉴런 수와 은닉층 뉴런 수의 차이의 절반과 동일하게 만드는 것입니다. \mln{2.5cm}{2}{3}를 사용할 때 사용 후 "yshift=0.5cm" 텍스트를 명확하게 렌더링하는 변수 \nodeoffset을 생성했습니다.

그 부분에 사용하려고 하면

% Draw the hidden layer nodes
    \foreach \name / \y in {1,...,\hidneuroncount}
        \path[\nodeoffset]

"패키지 pgfkeys 오류: '/tikz/yshift=0.5cm' 키를 모르므로 무시하겠습니다. 철자가 틀렸을 수도 있습니다."와 같은 오류가 발생합니다.

매개변수를 올바르게 가져오려면 어떻게 해야 합니까?

답변1

소위 확장 문제에 직면해 있습니다. 티케이Z는 매크로를 완전히 확장하지 않습니다 \nodeoffset. 교체하여 확장할 수 있습니다.

\path[\nodeoffset] node[hidden neuron] (H-\name) at (\layersep,-\y cm) {};

~에 의해

\path[style/.expanded=\nodeoffset] node[hidden neuron] (H-\name) at (\layersep,-\y cm) {};

전체 예:

\documentclass{article}
\usepackage{tikz}
\usepackage[nomessages]{fp}
\newcommand{\mln}[3]{
    \def\layersep{#1}
    \def\inpneuroncount{#2}
    \def\hidneuroncount{#3}

    \FPeval{result}{clip((\hidneuroncount-\inpneuroncount)/2)}
    \def\nodeoffset{yshift=\result cm}
    \nodeoffset

    \begin{tikzpicture}[shorten >=1pt,->,draw=black!50, node distance=\layersep]
        \tikzstyle{every pin edge}=[<-,shorten <=3pt]
        \tikzstyle{neuron}=[circle,fill=black!25,minimum size=15pt,inner sep=0pt]
        \tikzstyle{input neuron}=[neuron, fill=green!50];
        \tikzstyle{output neuron}=[neuron, fill=red!50];
        \tikzstyle{hidden neuron}=[neuron, fill=blue!50];
        \tikzstyle{annot} = [text width=4em, text centered]

        % Draw the input layer nodes
        \foreach \name / \y in {1,...,\inpneuroncount}
        % This is the same as writing \foreach \name / \y in {1/1,2/2,3/3,4/4}
            \node[input neuron, pin=left:Input \#\y] (I-\name) at (0,-\y) {};

        % Draw the hidden layer nodes
        \foreach \name / \y in {1,...,\hidneuroncount}
            \path[style/.expanded=\nodeoffset]
                node[hidden neuron] (H-\name) at (\layersep,-\y cm) {};

        % Draw the output layer node
        \node[output neuron,pin={[pin edge={->}]right:Output}, right of=H-1] (O) {};

        % Connect every node in the input layer with every node in the
        % hidden layer.
        \foreach \source in {1,...,\inpneuroncount}
            \foreach \dest in {1,...,\hidneuroncount}
                \path (I-\source) edge (H-\dest);

        % Connect every node in the hidden layer with the output layer
        \foreach \source in {1,...,\hidneuroncount}
            \path (H-\source) edge (O);

        % Annotate the layers
        \node[annot,above of=H-1, node distance=1cm] (hl) {Hidden layer};
        \node[annot,left of=hl] {Input layer};
        \node[annot,right of=hl] {Output layer};
    \end{tikzpicture}
    % End of code
}
\begin{document}
\mln{8em}{5}{4}
\end{document}

여기에 이미지 설명을 입력하세요

그러나 몇 가지 수정/개선을 제안하고 싶습니다.

  1. \tikzstyle더 이상 사용되지 않습니다. 대신 해당 \tikzset구문(아래 참조)을 사용하세요.
  2. 실제로는 여기에 필요하지 않습니다 fp.
  3. 사용 positioning.
  4. \def처음에 s는 실제로 목적이 없는 것 같습니다 .

이 밖에도 변경될 수 있는 사항이 많이 있지만 이는 부분적으로 수정된 버전입니다.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{positioning}
\newcommand{\mln}[3]{
    \begin{tikzpicture}[shorten >=1pt,->,draw=black!50, node distance=#1]
        \tikzset{every pin edge/.style={<-,shorten <=3pt},
          neuron/.style={circle,fill=black!25,minimum size=15pt,inner
            sep=0pt},
          input neuron/.style={neuron, fill=green!50},
          output neuron/.style={neuron, fill=red!50},
          hidden neuron/.style={neuron, fill=blue!50},
          annot/.style={text width=4em, text centered},
        my offset/.style={yshift={((#3-#2)/2)*1cm}}}
        \begin{scope}[local bounding box=diag]
          % Draw the input layer nodes
          \foreach \name / \y in {1,...,#2}
          % This is the same as writing \foreach \name / \y in {1/1,2/2,3/3,4/4}
              \node[input neuron, pin={[alias=auxI]left:Input \#\y}] (I-\name) at (0,-\y) {};

          % Draw the hidden layer nodes
          \foreach \name / \y in {1,...,#3}
              {\path[my offset]
                  node[hidden neuron] (H-\name) at (#1,-\y cm) {};}

          % Draw the output layer node
          \node[output neuron,pin={[pin edge={->},alias=auxO]right:Output}, right=of H-1] (O) {};

          % Connect every node in the input layer with every node in the
          % hidden layer.
          \foreach \source in {1,...,#2}
              \foreach \dest in {1,...,#3}
                  \path (I-\source) edge (H-\dest);

          % Connect every node in the hidden layer with the output layer
          \foreach \source in {1,...,#3}
              \path (H-\source) edge (O);
        \end{scope}
        % Annotate the layers
        \path ([yshift=1ex]diag.north-|H-1.center) node[anchor=south,annot] (hl) {Hidden layer};
        \path ([yshift=1ex]diag.north-|auxI.west) node[anchor=south west,annot]  {Input layer};
        \path ([yshift=1ex]diag.north-|auxO.east) node[anchor=south east,annot]  {Output layer};
    \end{tikzpicture}
    % End of code
}
\begin{document}
\mln{8em}{5}{4}
\end{document}

관련 정보