Bildunterschrift zentrieren, aber bestimmte Teile des TikZ-Bildes ignorieren

Bildunterschrift zentrieren, aber bestimmte Teile des TikZ-Bildes ignorieren

Betrachten Sie das folgende MWE:

\documentclass[a4paper]{scrartcl}

\usepackage{mathtools}
\usepackage{amssymb}

\usepackage[compatibility=false]{caption}
\usepackage[list]{subcaption}

\usepackage{fancyvrb}

\usepackage{tikz}
\usetikzlibrary{patterns, fit, positioning, calc, shapes.arrows}

\usepackage[active, tightpage, floats, displaymath]{preview}

\mathtoolsset{%
  mathic=true
}

% Vectors and matrices
\renewcommand*{\vec}[1]{\mathbf{#1}}
\newcommand{\mat}[1]{\mathbf{#1}}
\newcommand{\trans}{\intercal}

% Operators
\DeclareMathOperator{\rank}{rank}
\DeclareMathOperator*{\argmin}{arg\,min}
\DeclareMathOperator*{\argmax}{arg\,max}

\begin{document}
\begin{figure}
  \centering
  \captionsetup[subfigure]{margin={2.5cm, 0cm}}
  \begin{subfigure}[b]{0.60\textwidth}
    \centering
    \begin{tikzpicture}[>=latex, shorten >=2pt, shorten <=2pt]
      \node[draw, rectangle, label=below:the] (the) {\(\mat W\)};
      \node[draw, rectangle, right=of the, label=below:cat] (cat) {\(\mat W\)};
      \node[draw, rectangle, right=of cat, label=below:sat] (sat) {\(\mat W\)};

      \node[draw, rectangle, fit=(the.west) (the.east), pattern=vertical lines, above=of the] (in_the) {};
      \node[draw, rectangle, fit=(cat.west) (cat.east), pattern=vertical lines, above=of cat] (in_cat) {};
      \node[draw, rectangle, fit=(sat.west) (sat.east), pattern=vertical lines, above=of sat] (in_sat) {};

      \node[draw, rectangle, fit={($(cat.west) + (-8pt,0pt)$) ($(cat.east) + (8pt,0pt)$)}, pattern=vertical lines, above=2cm of cat] (in) {};
      \node[draw, rectangle, above=of in, label=above:mat] (out) {\(\vec b\), \(\mat U\)};

      \node[left=of the, outer sep=0] (embed) {embed};
      \node[above=2cm of embed, outer sep=0] (concatenate) {concatenate};
      \node[above=1cm of concatenate, outer sep=0] {softmax};

      \foreach \word in {the, cat, sat}{%
        \draw[->] (\word) -- (in_\word);
        \draw[->] (in_\word) -- (in);
      }

      \draw[->] (in) -- (out);
    \end{tikzpicture}
    \caption{CBOW model}\label{fig:cbow}
  \end{subfigure}
  \captionsetup[subfigure]{margin={0cm,0cm}}
  \begin{subfigure}[b]{0.35\textwidth}
    \centering
    \begin{tikzpicture}[>=latex, shorten >=2pt, shorten <=2pt]
      \node[draw, rectangle, label=below:cat] (cat) {\(\mat W\)};
      \node[draw, rectangle, fit=(cat.west) (cat.east), pattern=vertical lines, above=of cat] (in) {};
      \node[draw, rectangle, above=2cmof in, label=above:on] (on) {\(\vec b\), \(\mat U\)};
      \node[draw, rectangle, left=of on, label=above:sat] (sat) {\(\vec b\), \(\mat U\)};
      \node[draw, rectangle, right=of on, label=above:the] (the) {\(\vec b\), \(\mat U\)};

      \draw[->] (cat) -- (in);
      \foreach \word in {sat, on, the}{%
        \draw[->] (in) -- (\word);
      }
    \end{tikzpicture}
    \caption{Skip\=/gram model}\label{fig:sg}
  \end{subfigure}
  \caption{\protect\Verb+Word2Vec+ with vocabulary size \(V\), context
    size \(C\), and embedding size \(N\)}
\end{figure}
\end{document}

%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% End:

Welcher wird gesetzt in:

Word2Vec-Abbildung

Wie Sie sehen, habe ich die Überschrift „(a) CBOW-Modell“ mithilfe von „zentriert“ \captionsetup[subfigure]{margin={2.5cm, 0cm}}. Meine Frage ist: Ist es möglich, dies nicht tun zu müssen? Oder zumindest irgendwie die richtige Breite zu berechnen, um die ich die Überschrift verschieben muss?

Antwort1

Mit können Sie \useasboundingboxin TikZ die Größe des Bildes festlegen. TikZ ignoriert dann alles, was nach diesem Befehl kommt, bei der Berechnung der Bildgröße. Mit (current bounding box)können Sie die Größe des Bildes bis jetzt referenzieren. Wenn Sie alles, was für die Papiergröße zählen soll, vor die Linie zeichnen, \useasboundingbox (current bounding box)hat das Bild die gewünschte Größe.

Zusätzlich subfigurewird ein Leerzeichen benötigt, um die Überlappung nach links zu ermöglichen. Es muss also das erste sein. Natürlich muss die Breite der linken (nun ja mittleren) Teilfigur angepasst werden.

\documentclass[a4paper]{scrartcl}

\usepackage{mathtools}
\usepackage{amssymb}

\usepackage[compatibility=false]{caption}
\usepackage[list]{subcaption}

\usepackage{fancyvrb}

\usepackage{tikz}
\usetikzlibrary{patterns, fit, positioning, calc, shapes.arrows}

\usepackage[active, tightpage, floats, displaymath]{preview}

\mathtoolsset{%
  mathic=true
}

% Vectors and matrices
\renewcommand*{\vec}[1]{\mathbf{#1}}
\newcommand{\mat}[1]{\mathbf{#1}}
\newcommand{\trans}{\intercal}

% Operators
\DeclareMathOperator{\rank}{rank}
\DeclareMathOperator*{\argmin}{arg\,min}
\DeclareMathOperator*{\argmax}{arg\,max}

\begin{document}
\begin{figure}
  \centering
% no longer needed
%  \captionsetup[subfigure]{margin={2.5cm, 0cm}}
  %empty subfugure to allow for overlap to the left
  \begin{subfigure}[b]{0.15\textwidth}
  \mbox{}
  \end{subfigure}
  \begin{subfigure}[b]{0.40\textwidth}
    \centering
    \begin{tikzpicture}[>=latex, shorten >=2pt, shorten <=2pt]
      \node[draw, rectangle, label=below:the] (the) {\(\mat W\)};
      \node[draw, rectangle, right=of the, label=below:cat] (cat) {\(\mat W\)};
      \node[draw, rectangle, right=of cat, label=below:sat] (sat) {\(\mat W\)};

      \node[draw, rectangle, fit=(the.west) (the.east), pattern=vertical lines, above=of the] (in_the) {};
      \node[draw, rectangle, fit=(cat.west) (cat.east), pattern=vertical lines, above=of cat] (in_cat) {};
      \node[draw, rectangle, fit=(sat.west) (sat.east), pattern=vertical lines, above=of sat] (in_sat) {};

      \node[draw, rectangle, fit={($(cat.west) + (-8pt,0pt)$) ($(cat.east) + (8pt,0pt)$)}, pattern=vertical lines, above=2cm of cat] (in) {};
      \node[draw, rectangle, above=of in, label=above:mat] (out) {\(\vec b\), \(\mat U\)};

      % set the picture size to everything drawn so far
      \useasboundingbox (current bounding box);

      % not taken into account for the picture size
      \node[left=of the, outer sep=0] (embed) {embed};
      \node[above=2cm of embed, outer sep=0] (concatenate) {concatenate};
      \node[above=1cm of concatenate, outer sep=0] {softmax};

      % this belongs to the main part, but it doesn't increase its size
      % otherwise it must be moved before \useasboundingbox
      \foreach \word in {the, cat, sat}{%
        \draw[->] (\word) -- (in_\word);
        \draw[->] (in_\word) -- (in);
      }

      \draw[->] (in) -- (out);
    \end{tikzpicture}
    \caption{CBOW model}\label{fig:cbow}
  \end{subfigure}
% no longer needed
%  \captionsetup[subfigure]{margin={0cm,0cm}}
  \begin{subfigure}[b]{0.35\textwidth}
    \centering
    \begin{tikzpicture}[>=latex, shorten >=2pt, shorten <=2pt]
      \node[draw, rectangle, label=below:cat] (cat) {\(\mat W\)};
      \node[draw, rectangle, fit=(cat.west) (cat.east), pattern=vertical lines, above=of cat] (in) {};
      \node[draw, rectangle, above=2cmof in, label=above:on] (on) {\(\vec b\), \(\mat U\)};
      \node[draw, rectangle, left=of on, label=above:sat] (sat) {\(\vec b\), \(\mat U\)};
      \node[draw, rectangle, right=of on, label=above:the] (the) {\(\vec b\), \(\mat U\)};

      \draw[->] (cat) -- (in);
      \foreach \word in {sat, on, the}{%
        \draw[->] (in) -- (\word);
      }
    \end{tikzpicture}
    \caption{Skip\=/gram model}\label{fig:sg}
  \end{subfigure}
  \caption{\protect\Verb+Word2Vec+ with vocabulary size \(V\), context
    size \(C\), and embedding size \(N\)}
\end{figure}
\end{document}

Antwort2

Dies ist eine (relativ) weniger einfache Methode als meine ursprüngliche (relativ) einfache Antwort, die etwas flexibler und ein klein wenig besser getestet ist. Sie erfordert etoolboxund xparse. (Auf Letzteres könnten Sie bei Bedarf problemlos verzichten, aber es ist praktisch.)

  • So wie ich es eingerichtet habe, werden dadurch alle tikzpictureUmgebungen geändert.

    • Es könnte bei Bedarf um \tikzMakros erweitert werden.

    • Wenn die globalen Auswirkungen unerwünscht sind, entfernen Sie die every pictureDefinition und verwenden Sie einfach mark outdas optionale Argument für tikzpicture.

  • Es ermöglicht die Anpassung des Materials auf der linken, rechten, beiden oder keinem.

\tikzmarkerwestDie einzige Voraussetzung für den einfachen Fall basierend auf dem MWE ist, dass Sie an der Stelle im Bild einfügen, an der Sie den linken Teil des Bildes markieren möchten \caption, in dem die Beschriftung platziert werden soll. Wenn Sie das Makro im Bild überhaupt nicht verwenden, fällt der Code einfach auf den linken Teil des Begrenzungsrahmens des Bildes zurück, wenn das Bild vollständig ist. Dies geschieht im zweiten subfigureBeispiel.

Dabei wird der Code des ersten subfigureumgestellt, so dass alles, was \captionignoriert werden soll, nach dem ersten Bildteil kommt. \tikzmarkerwestwird dann eingefügt, um an dieser Stelle die linke Seite zu markieren.

...
      \foreach \word in {the, cat, sat}{%
        \draw[->] (\word) -- (in_\word);
        \draw[->] (in_\word) -- (in);
      }
      \draw[->] (in) -- (out);

Das ist alles, was wir \captionfür die Platzierung verwenden möchten. Markieren Sie jetzt also die linke Seite des Bildes.

      \tikzmarkerwest

Jetzt platzieren wir das Zeug links von diesem Punkt, das \captionignoriert werden soll.

      \node[left=of the, outer sep=0] (embed) {embed};
      \node[above=2cm of embed, outer sep=0] (concatenate) {concatenate};
      \node[above=1cm of concatenate, outer sep=0] {softmax};

Nun machen wir das Bild fertig und ergänzen es wie gewohnt mit Bildunterschrift und Beschriftung.

    \end{tikzpicture}
    \caption{CBOW model}\label{fig:cbow}

angepasste Beschriftung

Für das Material auf der rechten Seite \tikzmarkereastkann anstelle von oder zusätzlich zu verwendet werden \tikzmarkerwest.

In manchen Fällen ist es umständlich oder unmöglich, den Code in einem Bild auf diese Weise neu anzuordnen. Er lässt sich einfach nicht oder nur schwer in der erforderlichen Reihenfolge darstellen. Aus diesem Grund unterstützt \tikzmarkereastund \tikzmarkerwestein optionales Argument. Falls angegeben, sollte dies eine Koordinate in runden Klammern sein, wie bei Koordinaten üblich. In diesem Fall wird beim Platzieren der Überschrift alles rechts oder links von der angegebenen Koordinate ignoriert.

Der Code, der dies unterstützt, definiert das Makro \tikzmarkerwestwie folgt.

\NewDocumentCommand \tikzmarkerwest { D () {current bounding box.west} } {%
  \coordinate (tikz marker west) at (#1);
  \let\tikzmarkerwestdefault\relax
}

Dadurch wird an der entsprechenden Stelle eine Koordinate erstellt (tikz marker west). Anschließend wird sichergestellt, dass \tikzmarkerwestdefaultnichts erfolgreich ausgeführt wird.

\tikzmarkereastist auf die gleiche Weise definiert.

\NewDocumentCommand \tikzmarkereast { D () {current bounding box.east} } {%
  \coordinate (tikz marker east) at (#1);
  \let\tikzmarkereastdefault\relax
}

Wir stellen sicher , dass \tikzmarkerwestdefaultund \tikzmarkereastdefiniert sind. Standardmäßig tun sie nichts.

\NewDocumentCommand \tikzmarkerwestdefault {} {}
\NewDocumentCommand \tikzmarkereastdefault {} {}

Nun zum TikZ-Code.

\tikzset{%

Der Stil mark outfügt Code hinzu, der am Anfang und Ende des aktuellen Bildes ausgeführt werden soll, wenn er im optionalen Argument für die Umgebung angegeben ist, oder bei allen Bildern, wenn die Konfiguration wie unten angegeben ist.

  mark out/.style={%
    execute at begin picture={%
      \RenewDocumentCommand \tikzmarkerwestdefault {}
      {%
        \coordinate (tikz marker west) at (current bounding box.west);
      }%
      \RenewDocumentCommand \tikzmarkereastdefault {}
      {%
        \coordinate (tikz marker east) at (current bounding box.east);
      }%
    },

Dadurch werden unsere \tikzmarkerwestdefaultund \tikzmarkereastdefaultMakros neu definiert, um Koordinaten (tikz marker west)und (tikz marker east)links und rechts des aktuellen Begrenzungsrahmens zu erstellen. Dies sind nur Definitionen, die die standardmäßigen leeren überschreiben. Sie erstellen noch keine Koordinaten.

    execute at end picture={%
      \tikzmarkerwestdefault
      \tikzmarkereastdefault

Am Ende des Bildes führen wir aus \tikzmarkerwestdefault. Wenn \tikzmarkerwestinnerhalb des Bildes aufgerufen wurde, wird dies nichts erfolgreich ausführen. Andernfalls wird der Marker links neben dem aktuellen Begrenzungsrahmen erstellt, der der endgültige Begrenzungsrahmen für das Bild ist. Gleiches gilt für \tikzmarkereastdefault.

      \path let \p1=(tikz marker west), \p2=(current bounding box.west), \n1={\x1-\x2} in \pgfextra{\xdef\myadjustwest{\n1}} ;

Dies berechnet die Differenz zwischen dem xTeil der (tikz marker west)Koordinate und dem xTeil der Koordinate links vom aktuellen Begrenzungsrahmen. Normalerweise ist dies 0pt. Wenn jedoch \tikzmarkerwestaufgerufen wurde, kann der Abstand des Markierungsknotens von der linken Seite des aktuellen Begrenzungsrahmens ungleich Null sein. (Wenn das Makro aufgerufen wurde, wird dies vermutlich der Fall sein, da dies der einzige Grund ist, das Makro zu verwenden.)

Jetzt machen wir dasselbe für (tikz marker east)und rechts vom aktuellen Begrenzungsrahmen.

      \path let \p1=(tikz marker east), \p2=(current bounding box.east), \n1={\x2-\x1} in \pgfextra{\xdef\myadjusteast{\n1}} ;
    },
  },


  every picture/.style={mark out},

Diese Linie wendet den mark outStil auf alle Ti ankZ-Bilder. Wenn dies Probleme verursacht, entfernen Sie es und fügen Sie es mark outden Bildern hinzu, für die Sie es möchten.

}
\newlength\myadjustwest
\newlength\myadjusteast

Stellen Sie sicher \myadjustwest, dass \myadjusteastSie unabhängig davon verfügbar sind.

\AfterEndEnvironment{tikzpicture}{%
  \captionsetup{margin={\myadjustwest,\myadjusteast}}%
}{\typeout{OK!}}{\typeout{Oh, no!}}

Dies passt das Ende aller tikzpictureUmgebungen an, um die korrekt zu ändern . Wenn Sie dies verwenden, \captionsollten Sie anstelle von OK!und aussagekräftige Nachrichten für sich selbst verwenden.Oh, no!

Der folgende Beispielsatz veranschaulicht die grundlegenden Möglichkeiten. Wenn Sie die Überschrift relativ zu beispielsweise einem schattierten Rechteck platzieren möchten, können Sie nicht (ganz einfach) einen Teil davon schattieren, dann einen anderen Teil und dann noch einen Teil, wobei Sie den Begrenzungsrahmen zwischen den Stufen entsprechend markieren. Daher verwenden wir für diesen Fall die optionalen Argumente für \tikzmarkerwestund/oder \tikzmarkereast, um Positionen für Überschriften zu erhalten, die sich auf das rote Ende des sichtbaren Lichtspektrums, das blaue Ende und ein Zwischenstück links von der Mitte konzentrieren.

Für die Roten...

...
      \shade [shading=wave, shading angle=90] (0,0) rectangle ++(\linewidth,1) coordinate [pos=.4] (r);
      \tikzmarkereast(r)
...

Für den Blues...

...
      \shade [shading=wave, shading angle=90] (0,0) rectangle ++(\linewidth,1) coordinate [pos=.6] (b);
      \tikzmarkerwest(b)
...

Für die Innereien...

...
      \shade [shading=wave, shading angle=90] (0,0) rectangle ++(\linewidth,1) coordinate [pos=.1] (a) coordinate [pos=.5] (b);
      \tikzmarkereast(b)
      \tikzmarkerwest(a)
...

angepasste Bildunterschriften für das sichtbare Lichtspektrum

Vollständiger Code:

% arara: pdflatex
\pdfminorversion=7
% ateb: https://tex.stackexchange.com/a/377652/ addaswyd o gwestiwn d125q: https://tex.stackexchange.com/q/377476/
\documentclass[a4paper]{scrartcl}
\usepackage{mathtools,amssymb}
\usepackage[compatibility=false]{caption}
\usepackage[list]{subcaption}
\usepackage{fancyvrb,tikz,etoolbox,xparse}
\usetikzlibrary{patterns, fit, positioning, calc}
\usepackage[active, tightpage, floats, displaymath]{preview}
\mathtoolsset{%
  mathic=true
}
\NewDocumentCommand \tikzmarkerwest { D () {current bounding box.west} } {%
  \coordinate (tikz marker west) at (#1);
  \let\tikzmarkerwestdefault\relax
}
\NewDocumentCommand \tikzmarkerwestdefault {} {}
\NewDocumentCommand \tikzmarkereast { D () {current bounding box.east} } {%
  \coordinate (tikz marker east) at (#1);
  \let\tikzmarkereastdefault\relax
}
\NewDocumentCommand \tikzmarkereastdefault {} {}
\tikzset{%
  mark out/.style={%
    execute at begin picture={%
      \RenewDocumentCommand \tikzmarkerwestdefault {}
      {%
        \coordinate (tikz marker west) at (current bounding box.west);
      }%
      \RenewDocumentCommand \tikzmarkereastdefault {}
      {%
        \coordinate (tikz marker east) at (current bounding box.east);
      }%
    },
    execute at end picture={%
      \tikzmarkerwestdefault
      \tikzmarkereastdefault
      \path let \p1=(tikz marker west), \p2=(current bounding box.west), \n1={\x1-\x2} in \pgfextra{\xdef\myadjustwest{\n1}} ;
      \path let \p1=(tikz marker east), \p2=(current bounding box.east), \n1={\x2-\x1} in \pgfextra{\xdef\myadjusteast{\n1}} ;
    },
  },
  every picture/.style={mark out},
}
\newlength\myadjustwest
\newlength\myadjusteast
\AfterEndEnvironment{tikzpicture}{%
  \captionsetup{margin={\myadjustwest,\myadjusteast}}%
}{\typeout{OK!}}{\typeout{Oh, no!}}

% for the examples
\definecolor{wave start}{wave}{380}
\definecolor{wave violet}{wave}{400}
\definecolor{wave indigo}{wave}{445}
\definecolor{wave blue}{wave}{475}
\definecolor{wave green}{wave}{510}
\definecolor{wave yellow}{wave}{570}
\definecolor{wave orange}{wave}{590}
\definecolor{wave red}{wave}{650}
\definecolor{wave end}{wave}{780}
\pgfdeclareverticalshading{wave}{100bp}{% manual 1088; xcolor manual; does not work to use wave model directly (?); https://science-edu.larc.nasa.gov/EDDOCS/Wavelengths_for_Colors.html
  color(0bp)=(wave start);
  color(25bp)=(wave start);
  color(27bp)=(wave violet);% 400 nm
  color(33bp)=(wave indigo);% 445nm
  color(37bp)=(wave blue);% 475nm
  color(41bp)=(wave green);% 510nm
  color(49bp)=(wave yellow);% 570nm
  color(51bp)=(wave orange);% 590nm
  color(59bp)=(wave red);% 650nm
  color(75bp)=(wave end);% 780nm
  color(100bp)=(wave end)
}
\begin{document}
\begin{figure}
  \centering
  \begin{subfigure}[b]{0.60\textwidth}
    \centering
    \begin{tikzpicture}[>=latex, shorten >=2pt, shorten <=2pt]
      \node[draw, label=below:the] (the) {\(\mathbf{W}\)};
      \node[draw, right=of the, label=below:cat] (cat) {\(\mathbf{W}\)};
      \node[draw, right=of cat, label=below:sat] (sat) {\(\mathbf{W}\)};
      \node[draw, fit=(the.west) (the.east), pattern=vertical lines, above=of the] (in_the) {};
      \node[draw, fit=(cat.west) (cat.east), pattern=vertical lines, above=of cat] (in_cat) {};
      \node[draw, fit=(sat.west) (sat.east), pattern=vertical lines, above=of sat] (in_sat) {};
      \node[draw, fit={($(cat.west) + (-8pt,0pt)$) ($(cat.east) + (8pt,0pt)$)}, pattern=vertical lines, above=2cm of cat] (in) {};
      \node[draw, above=of in, label=above:mat] (out) {\(\mathbf{b}\), \(\mathbf{U}\)};
      \foreach \word in {the, cat, sat}{%
        \draw[->] (\word) -- (in_\word);
        \draw[->] (in_\word) -- (in);
      }
      \draw[->] (in) -- (out);
      \tikzmarkerwest
      \node[left=of the, outer sep=0] (embed) {embed};
      \node[above=2cm of embed, outer sep=0] (concatenate) {concatenate};
      \node[above=1cm of concatenate, outer sep=0] {softmax};
    \end{tikzpicture}
    \caption{CBOW model}\label{fig:cbow}
  \end{subfigure}
  \begin{subfigure}[b]{0.35\textwidth}
    \centering
    \begin{tikzpicture}[>=latex, shorten >=2pt, shorten <=2pt]
      \node[draw, label=below:cat] (cat) {\(\mathbf{W}\)};
      \node[draw, fit=(cat.west) (cat.east), pattern=vertical lines, above=of cat] (in) {};
      \node[draw, above=2cmof in, label=above:on] (on) {\(\mathbf{b}\), \(\mathbf{U}\)};
      \node[draw, left=of on, label=above:sat] (sat) {\(\mathbf{b}\), \(\mathbf{U}\)};
      \node[draw, right=of on, label=above:the] (the) {\(\mathbf{b}\), \(\mathbf{U}\)};
      \draw[->] (cat) -- (in);
      \foreach \word in {sat, on, the}{%
        \draw[->] (in) -- (\word);
      }
    \end{tikzpicture}
    \caption{Skip\=/gram model}\label{fig:sg}
  \end{subfigure}
  \caption{\protect\Verb+Word2Vec+ with vocabulary size \(V\), context size \(C\), and embedding size \(N\)}
\end{figure}

\begin{figure}
  \centering
  \begin{subfigure}{.33\linewidth}
    \centering
    \begin{tikzpicture}
      \shade [shading=wave, shading angle=90] (0,0) rectangle ++(\linewidth,1) coordinate [pos=.4] (r);
      \tikzmarkereast(r)
    \end{tikzpicture}
    \caption{Reds.}
  \end{subfigure}\hfill
  \begin{subfigure}{.33\linewidth}
    \centering
    \begin{tikzpicture}
      \shade [shading=wave, shading angle=90] (0,0) rectangle ++(\linewidth,1) coordinate [pos=.6] (b);
      \tikzmarkerwest(b)
    \end{tikzpicture}
    \caption{Blues.}
  \end{subfigure}\hfill
  \begin{subfigure}{.33\linewidth}
    \centering
    \begin{tikzpicture}
      \shade [shading=wave, shading angle=90] (0,0) rectangle ++(\linewidth,1) coordinate [pos=.1] (a) coordinate [pos=.5] (b);
      \tikzmarkereast(b)
      \tikzmarkerwest(a)
    \end{tikzpicture}
    \caption{Innards.}
  \end{subfigure}\par
  \caption{Main figure}
\end{figure}
\end{document}

Antwort3

Erstens habe ich meine erste Antwort nicht bearbeitet, da sie für manche Leute möglicherweise so, wie sie ist, nützlich ist.

Diese neue Antwort berechnet die Ränder für die Überschrift. Dazu gibt es in der Präambel einige Makros. Und dann müssen drei Befehle platziert werden. Sie sind alle ohne Argumente.

Im Bild muss zuerst der Hauptteil (also der Teil, unter dem die Überschrift zentriert werden soll) gezeichnet werden. Dann \pgfremembermainxmuss eingefügt werden. Dabei werden Koordinaten gesetzt, um sich die äußersten x-Positionen bis jetzt zu merken. Danach müssen die Teile gezeichnet werden, die den Hauptteil links und rechts überlappen.

Ganz am Ende, kurz vor \end{tikzpicture}, muss der Befehl \pgfgetoverlapstehen. Er berechnet den Überlapp (relativ zum Hauptteil) zu beiden Seiten und speichert diese in den Dimensionsregistern \overlapleftund \overlapright. Beide sind global gesetzt, können also nach dem verwendet werden tikzpicture. Hinweis: alles was danach gezeichnet wird, \pgfgetoverlapwird bei der Berechnung des Überlapps nicht berücksichtigt.

Und zum Schluss tikzpicturewerden mit die Ränder zwischen dem Bild und der Beschriftung gesetzt \captionsetmargins. Die Wirkung ist lokal, da es sich in der subfigureUmgebung befindet. Außerhalb der Umgebung sollte es nicht verwendet werden, da es die Ränder für alle Beschriftungen setzen würde, da das optionale Argument ( [subfigure]) hier nicht verwendet werden kann. Natürlich funktioniert das nur nach dem Bild, da die Überlappungen vorher nicht bekannt sind.

\documentclass[a4paper]{scrartcl}

\usepackage{mathtools}
\usepackage{amssymb}

\usepackage[compatibility=false]{caption}
\usepackage[list]{subcaption}

\usepackage{fancyvrb}

\usepackage{tikz}
\usetikzlibrary{patterns, fit, positioning, calc, shapes.arrows}

\usepackage[active, tightpage, floats, displaymath]{preview}

\mathtoolsset{%
  mathic=true
}

% Vectors and matrices
\renewcommand*{\vec}[1]{\mathbf{#1}}
\newcommand{\mat}[1]{\mathbf{#1}}
\newcommand{\trans}{\intercal}

% Operators
\DeclareMathOperator{\rank}{rank}
\DeclareMathOperator*{\argmin}{arg\,min}
\DeclareMathOperator*{\argmax}{arg\,max}

%---------------------------------------------------------------------
% code for automatic setting of caption margins
\makeatletter
\newdimen\overlapleft
\newdimen\overlapright

\newcommand{\pgfremembermainx}{%
    \coordinate (main west) at (current bounding box.west);
    \coordinate (main east) at (current bounding box.east);
}
\newcommand{\pgfgetoverlap}{%
    \pgfextractx{\@tempdima}{%
        \pgfpointdiff{\pgfpointanchor{current bounding box}{west}}%
                     {\pgfpointanchor{main west}{center}}%
    }%
    \global\overlapleft=\@tempdima
    \pgfextractx{\@tempdima}{%
        \pgfpointdiff{\pgfpointanchor{main east}{center}}%
                     {\pgfpointanchor{current bounding box}{east}}%
    }%
    \global\overlapright=\@tempdima
}
\newcommand{\captionsetmargins}{%
    % no additional calculation required here
    \captionsetup{margin={\overlapleft,\overlapright}}%
}
\makeatother
%---------------------------------------------------------------------

\begin{document}
\begin{figure}
  \centering
% not needed here
%  \captionsetup[subfigure]{margin={2.5cm, 0cm}}
  \begin{subfigure}[b]{0.60\textwidth}
    \centering
    \begin{tikzpicture}[>=latex, shorten >=2pt, shorten <=2pt]
      \node[draw, rectangle, label=below:the] (the) {\(\mat W\)};
      \node[draw, rectangle, right=of the, label=below:cat] (cat) {\(\mat W\)};
      \node[draw, rectangle, right=of cat, label=below:sat] (sat) {\(\mat W\)};

      \node[draw, rectangle, fit=(the.west) (the.east), pattern=vertical lines, above=of the] (in_the) {};
      \node[draw, rectangle, fit=(cat.west) (cat.east), pattern=vertical lines, above=of cat] (in_cat) {};
      \node[draw, rectangle, fit=(sat.west) (sat.east), pattern=vertical lines, above=of sat] (in_sat) {};

      \node[draw, rectangle, fit={($(cat.west) + (-8pt,0pt)$) ($(cat.east) + (8pt,0pt)$)}, pattern=vertical lines, above=2cm of cat] (in) {};
      \node[draw, rectangle, above=of in, label=above:mat] (out) {\(\vec b\), \(\mat U\)};

      % remember the x-coordinates of the main part      
      \pgfremembermainx
      % \useasboundingbox was here in the first answer

      % not taken into account for the picture size
      \node[left=of the, outer sep=0] (embed) {embed};
      \node[above=2cm of embed, outer sep=0] (concatenate) {concatenate};
      \node[above=1cm of concatenate, outer sep=0] {softmax};

      % this belongs to the main part, but it doesn't increase its size
      % otherwise it must be moved before \pgfremembermainx
      \foreach \word in {the, cat, sat}{%
        \draw[->] (\word) -- (in_\word);
        \draw[->] (in_\word) -- (in);
      }

      \draw[->] (in) -- (out);

      %for testing, if it also works with overlap to the right
      %\node[draw, right= of sat] {t};

      % must be right before \end{tikzpicture}, everything after it
      % would not be taken into account for the calculation of the overlap
      \pgfgetoverlap
    \end{tikzpicture}
    % setting the caption margins
    % moving this here sets the margin locally (only for the current environment)
    % and here the computed values for the margins are known
    \captionsetmargins
    \caption{CBOW model}\label{fig:cbow}
  \end{subfigure}
% no longer needed
%  \captionsetup[subfigure]{margin={0cm,0cm}}
  \begin{subfigure}[b]{0.35\textwidth}
    \centering
    \begin{tikzpicture}[>=latex, shorten >=2pt, shorten <=2pt]
      \node[draw, rectangle, label=below:cat] (cat) {\(\mat W\)};
      \node[draw, rectangle, fit=(cat.west) (cat.east), pattern=vertical lines, above=of cat] (in) {};
      \node[draw, rectangle, above=2cmof in, label=above:on] (on) {\(\vec b\), \(\mat U\)};
      \node[draw, rectangle, left=of on, label=above:sat] (sat) {\(\vec b\), \(\mat U\)};
      \node[draw, rectangle, right=of on, label=above:the] (the) {\(\vec b\), \(\mat U\)};

      \draw[->] (cat) -- (in);
      \foreach \word in {sat, on, the}{%
        \draw[->] (in) -- (\word);
      }
    \end{tikzpicture}
    \caption{Skip\=/gram model}\label{fig:sg}
  \end{subfigure}
  \caption{\protect\Verb+Word2Vec+ with vocabulary size \(V\), context
    size \(C\), and embedding size \(N\)}
\end{figure}
\end{document}

verwandte Informationen