Centrar el título pero ignorar ciertas partes de la imagen de TikZ

Centrar el título pero ignorar ciertas partes de la imagen de TikZ

Considere el siguiente 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:

Que se compone en:

Ilustración Word2Vec

Como puede ver, he "centrado" el título "(a) modelo CBOW" usando \captionsetup[subfigure]{margin={2.5cm, 0cm}}. Mi pregunta es: ¿es posible no tener que hacer esto? ¿O al menos calcular de alguna manera el ancho correcto por el cual necesito compensar el título?

Respuesta1

Puedes usarlo \useasboundingboxen TikZ para establecer la dimensión de la imagen. Luego, TikZ ignorará todo lo que haya después de ese comando para calcular el tamaño de la imagen. Con (current bounding box)puedes consultar el tamaño de la imagen hasta el momento. Mientras dibujes todo lo que debería contar para el tamaño del papel, antes de la línea \useasboundingbox (current bounding box)la imagen tendrá el tamaño deseado.

Además, se necesita un vacío subfigurepara permitir la superposición hacia la izquierda. Entonces tiene que ser el primero. Por supuesto, es necesario ajustar el ancho de la subfigura izquierda (bueno, ahora la del medio).

\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}

Respuesta2

Este es un método (relativamente) menos simple que mi respuesta original (relativamente) simple, que es un poco más flexible y ligeramente mejor probada. Requiere etoolboxy xparse. (Si lo desea, puede prescindir fácilmente de este último, pero es conveniente).

  • Tal como configuré las cosas, esto modifica todos tikzpicturelos entornos.

    • Podría ampliarse para incluir \tikzmacros, si fuera necesario.

    • Si el impacto global no es deseable, elimine la every picturedefinición y simplemente utilícela mark outen el argumento opcional to tikzpicture.

  • Permite el ajuste del material a la izquierda, a la derecha, a ambos o a ninguno.

El único requisito para el caso simple basado en el MWE es insertar \tikzmarkerwesten el punto de la imagen donde se desea marcar la parte izquierda de la imagen que \captionse debe utilizar para colocar el título. Si no utiliza la macro en absoluto en la imagen, el código simplemente vuelve a caer a la izquierda del cuadro delimitador de la imagen, cuando la imagen está completa. Esto sucede en el segundo subfiguredel ejemplo.

El código del primero subfigurese reordena, de modo que todo lo que \captionse debe ignorar viene después de la primera parte de la imagen. \tikzmarkerwestLuego se inserta para marcar el lado izquierdo en este punto.

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

Eso es todo lo que queremos \captionusar para la ubicación, así que marque ahora la izquierda de la imagen.

      \tikzmarkerwest

Ahora ponemos las cosas a la izquierda de ese punto, que \captiondeberíamos ignorar.

      \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};

Ahora terminamos la imagen y agregamos el título y la etiqueta como de costumbre.

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

título ajustado

Para el material de la derecha, \tikzmarkereastse puede utilizar en lugar de o además de \tikzmarkerwest.

En algunos casos, resulta inconveniente o imposible reorganizar el código de una imagen de esta manera. Simplemente no se puede dibujar fácilmente, en todo caso, en el orden requerido. Por este motivo, \tikzmarkereastapoye \tikzmarkerwestun argumento opcional. Si se especifica, debería ser una coordenada entre paréntesis, como es habitual para las coordenadas. En este caso, todo lo que esté a la derecha o izquierda de la coordenada especificada se ignorará al colocar el título.

El código que admite esto define la macro \tikzmarkerwestde la siguiente manera.

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

Esto crea una coordenada (tikz marker west)en el lugar apropiado. Luego se asegura de que \tikzmarkerwestdefaultno haga nada correctamente.

\tikzmarkereastse define de la misma manera.

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

Nos aseguramos \tikzmarkerwestdefaulty \tikzmarkereastestamos definidos. Por defecto, no hacen nada.

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

Ahora para el TikCódigo Z.

\tikzset{%

El estilo mark outagrega código que se ejecutará al principio y al final de la imagen actual, si se proporciona en el argumento opcional del entorno, o de todas las imágenes, si se configura como se muestra a continuación.

  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);
      }%
    },

Esto redefine nuestras macros \tikzmarkerwestdefaulty \tikzmarkereastdefaultpara crear coordenadas (tikz marker west)y (tikz marker east)a la izquierda y a la derecha del cuadro delimitador actual. Estas son sólo definiciones, que anulan las vacías predeterminadas. En realidad, todavía no crean ninguna coordenada.

    execute at end picture={%
      \tikzmarkerwestdefault
      \tikzmarkereastdefault

Al final de la imagen ejecutamos \tikzmarkerwestdefault. Si \tikzmarkerwestse ha llamado dentro de la imagen, esto no hará nada con éxito. De lo contrario, creará el marcador a la izquierda del cuadro delimitador actual, que es el cuadro delimitador final de la imagen. De manera similar para \tikzmarkereastdefault.

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

Esto calcula la diferencia entre la xparte de la (tikz marker west)coordenada y la xparte de la coordenada a la izquierda del cuadro delimitador actual. Normalmente, será 0 puntos. Pero, si \tikzmarkerwestse ha llamado, la distancia del nodo marcador desde la izquierda del cuadro delimitador actual puede ser distinta de cero. (De hecho, si se ha llamado a la macro, presumiblemente este será el caso, ya que esa es la única razón para usar la macro).

Ahora hacemos lo mismo para (tikz marker east)y a la derecha del cuadro delimitador actual.

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


  every picture/.style={mark out},

Esta línea aplica el mark outestilo a todos los Ti.kImágenes Z. Si esto causa problemas, elimínelo y agréguelo mark outa las imágenes para las que lo desea.

}
\newlength\myadjustwest
\newlength\myadjusteast

Asegúrese \myadjustwesty \myadjusteastesté disponible independientemente.

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

Esto adapta el final de todos tikzpicturelos entornos para modificarlos \captioncorrectamente. Debes sustituir mensajes significativos en lugar de OK!y Oh, no!, si usas esto.

El siguiente conjunto de ejemplos ilustra las posibilidades básicas. Si desea colocar el título en relación con, digamos, un rectángulo sombreado, no puede (nada fácilmente) sombrear una parte del mismo, luego otra parte y luego otra parte, marcando apropiadamente el cuadro delimitador entre las etapas. Por lo tanto, para este caso, utilizamos los argumentos opcionales for \tikzmarkerwesty/o \tikzmarkereastpara obtener posiciones para los subtítulos que se centran en el extremo rojo del espectro de luz visible, el extremo azul y un bit intermedio a la izquierda del centro.

Para los rojos...

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

Para los azules...

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

Para las entrañas...

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

subtítulos ajustados para el espectro de luz visible

Código completo:

% 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}

Respuesta3

Primero, no edité mi primera respuesta, porque tal como está podría ser útil para algunas personas.

Esta nueva respuesta calcula los márgenes del título. Para ello hay algunas macros en el preámbulo. Y luego hay que colocar tres comandos. Todos ellos están sin ningún argumento.

En la imagen, primero se debe dibujar la parte principal (es decir, la parte bajo la cual se debe centrar el título). Luego \pgfremembermainxhay que insertarlo. Estableció coordenadas para recordar las posiciones x más externas hasta el momento. Después de eso, se deben dibujar las partes que se superponen a la parte principal a la izquierda y a la derecha.

Justo al final, justo antes , se debe colocar \end{tikzpicture}el comando . \pgfgetoverlapCalcula la superposición (en relación con la parte principal) en ambos lados y los almacena en los registros de dimensiones \overlaplefty \overlapright. Ambos están configurados de forma global, por lo que se pueden utilizar después del archivo tikzpicture. Nota: todo lo que se dibuje después \pgfgetoverlapno se tendrá en cuenta para calcular la superposición.

Y finalmente entre el tikzpicturey el título se establecen los márgenes con \captionsetmargins. Su efecto es local ya que está en el subfiguremedio ambiente. No debe usarse fuera del entorno, porque establecería los márgenes para todos los títulos ya que el argumento opcional ( [subfigure]) no se puede usar aquí. Por supuesto, esto sólo funciona después de la imagen, porque antes de ella no se conocen las superposiciones.

\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}

información relacionada