出于教学目的,我试图解释线性回归的基本工作原理以及如何扩展它。由于我不是 TeXpert,我担心我的想法可能很棘手,而且比它可能的难度更大。我见过许多带有和的漂亮tikz
图pgfplots
。
我四处寻找,最终找到了下面的图片。
这幅图看起来非常合适,因为我可以解释回归可能是什么样子。但问题是我无法操作,例如绘制网格、更改x_0
resp的命名\epsilon
、将红线更改为虚线、添加除 P 和 Q 之外的其他点等。如果函数本身是x^2
或某种混合,我不介意解释。我的主要目的是说明基本思想。如果我有一个样本,那么我可以将其进一步扩展到均值、方差等。
有人愿意帮我吗?如果有人能给我提供一些现有的样本,我并不介意。这样也很好。
答案1
使用 TikZ 非常简单。我使用了 Plain TeX,因此您需要在文档末尾使用\input tikz.tex
而不是\usepackage{tikz}
和 而不是。\begin{document}...\end{document}
\bye
使用以下代码排版pdftex
\input tikz.tex
\nopagenumbers% for cropping
\usetikzlibrary{arrows,intersections}
\tikzpicture[
thick,
>=stealth',
dot/.style = {
draw,
fill=white,
circle,
inner sep=0pt,
minimum size=4pt
}
]
\coordinate (O) at (0,0);
\draw[->] (-0.3,0) -- (8,0) coordinate[label={below:$x$}] (xmax);
\draw[->] (0,-0.3) -- (0,5) coordinate[label={right:$f(x)$}] (ymax);
\path[name path=x] (0.3,0.5) -- (6.7,4.7);
\path[name path=y] plot[smooth] coordinates {(-0.3,2) (2,1.5) (4,2.8) (6,5)};
\scope[name intersections={of=x and y,name=i}]
\fill[gray!20] (i-1) -- (i-2 |- i-1) -- (i-2) -- cycle;
\draw (0.3,0.5) -- (6.7,4.7) node[pos=0.8,below right] {Sekante};
\draw[red] plot[smooth] coordinates {(-0.3,2) (2,1.5) (4,2.8) (6,5)};
\draw (i-1) node[dot,label={above:$P$}] (i-1) {} -- node[left] {$f(x_0)$} (i-1 |- O) node[dot,label={below:$x_0$}] {};
\path (i-2) node[dot,label={above:$Q$}] (i-2) {} -- (i-2 |- i-1) node[dot] (i-12) {};
\draw (i-12) -- (i-12 |- O) node[dot,label={below:$x_0 + \varepsilon$}] {};
\draw[blue,<->] (i-2) -- node[right] {$f(x_0 + \varepsilon) - f(x_0)$} (i-12);
\draw[blue,<->] (i-1) -- node[below] {$\varepsilon$} (i-12);
\path (i-1 |- O) -- node[below] {$\varepsilon$} (i-2 |- O);
\draw[gray] (i-2) -- (i-2 -| xmax);
\draw[gray,<->] ([xshift=-0.5cm]i-2 -| xmax) -- node[fill=white] {$f(x_0 + \varepsilon)$} ([xshift=-0.5cm]xmax);
\endscope
\endtikzpicture
\bye
这将产生以下输出(裁剪)
由于交点是由intersections
库计算的,因此该解决方案是自适应的。在此代码中,实际上不是点 Q 移动,而是红线上的某个点移动,这导致 Q 移动(如果仔细观察,您会发现,当 Q 向右移动时,红线会出现难看的凸起)。
我创建动画的工作流程如下:
- 修改源文件,使得对于每个变化在输出中创建一个单独的页面(大多数情况下使用 PGF
\foreach
循环,像这里一样) - 使用 Heiko Oberdiek 的 裁剪生成的 PDF
pdfcrop
。 - 导入裁剪后的 PDFGIMP。
- 在 GIMP 中:反转图层顺序并导出,就像选中
.gif
选项一样As Animation
,延迟 200 毫秒(否则对我来说太快了)。
下面包含用于创建动画的代码。我标记了与上面的代码相比需要额外修改的行。
\input tikz.tex
\nopagenumbers% for cropping
\usetikzlibrary{arrows,intersections}
\foreach \Q in {4,4.1,4.2,...,5,4.9,4.8,...,4.1} {%<-- added
\tikzpicture[
thick,
>=stealth',
dot/.style = {
draw,
fill=white,
circle,
inner sep=0pt,
minimum size=4pt
}
]
\coordinate (O) at (0,0);
\draw[->] (-0.3,0) -- (8,0) coordinate[label={below:$x$}] (xmax);
\draw[->] (0,-0.3) -- (0,5) coordinate[label={right:$f(x)$}] (ymax);
\path[name path=x] (0.3,0.5) -- (6.7,4.7);
\path[name path=y] plot[smooth] coordinates {(-0.3,2) (2,1.5) (\Q,2.8) (6,5)};%<-- modified
\scope[name intersections={of=x and y,name=i}]
\fill[gray!20] (i-1) -- (i-2 |- i-1) -- (i-2) -- cycle;
\draw (0.3,0.5) -- (6.7,4.7) node[pos=0.8,below right] {Sekante};
\draw[red] plot[smooth] coordinates {(-0.3,2) (2,1.5) (\Q,2.8) (6,5)};%<-- modified
\draw (i-1) node[dot,label={above:$P$}] (i-1) {} -- node[left] {$f(x_0)$} (i-1 |- O) node[dot,label={below:$x_0$}] {};
\path (i-2) node[dot,label={above:$Q$}] (i-2) {} -- (i-2 |- i-1) node[dot] (i-12) {};
\draw (i-12) -- (i-12 |- O) node[dot,label={below:$x_0 + \varepsilon$}] {};
\draw[blue,<->] (i-2) -- node[right] {$f(x_0 + \varepsilon) - f(x_0)$} (i-12);
\draw[blue,<->] (i-1) -- node[below] {$\varepsilon$} (i-12);
\path (i-1 |- O) -- node[below] {$\varepsilon$} (i-2 |- O);
\draw[gray] (i-2) -- (i-2 -| xmax);
\draw[gray,<->] ([xshift=-0.5cm]i-2 -| xmax) -- node[fill=white] {$f(x_0 + \varepsilon)$} ([xshift=-0.5cm]xmax);
\endscope
\endtikzpicture
\eject%<-- added
}%<-- added
\bye
答案2
我对 TikZ 的尝试。请注意,代码可能可以更紧凑,但为了使其尽可能易于理解,我选择使其稍微冗长一些。
\documentclass[tikz,border=3pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,calc}
\begin{document}
\begin{tikzpicture}[>=stealth',
dot/.style={circle,draw,fill=white,inner sep=0pt,minimum size=4pt}]
% draw axis lines
\draw[->,thick] (-0.5,0) -- ++(11,0) node[below left]{$x$};
\draw[->,thick] (0,-0.5) -- ++(0,7) node[below right]{$f(x)$};
\coordinate (O) at (0,0);
% create path for function curve
\path[thick,red] (-0.3,2) to[out=-25, in=200] coordinate[pos=0.2] (p) coordinate[pos=0.6] (q) (9,5);
% fill area
\fill[blue, opacity=.1] (p) -| (q);
% draw the secant line with fixed length
\draw[shorten <=-1.5cm] (p) -- ($ (p)!7.5cm!(q) $) node[below right, pos=0.9]{Sekante};
% draw function curve
\draw[thick,red] (-0.3,2) to[out=-25, in=200] (9,5);
% draw all points
\node[dot,label={above:$P$}] (P) at (p) {};
\node[dot,label={above:$Q$}] (Q) at (q) {};
\node[dot] (p1) at (P |- O) {};
\node[dot] (p2) at (Q |- O) {};
\node[dot] (p3) at (P -| Q) {};
% draw lines between nodes and place text
\draw (P) -- node[left]{$f(x_{0})$} (p1) node[dot,label={below:$x_{0}$}]{};
\draw (p2) node[dot,label={below:$x_{0} + \varepsilon$}]{} -- (p3);
\path (p1) -- node[below]{$\varepsilon$} (p2);
% draw blue arrows between nodes
\draw[<->,blue,thick] (P) -- node[below]{$\varepsilon$} (p3);
\draw[<->,blue,thick] (Q) -- node[right]{$f(x_{0} + \varepsilon) - f(x_{0})$} (p3);
% draw the explanation for the y-value of point Q
\draw[help lines] (Q) -- (Q -| {(9.5,0)}) ++(-0.5,0) coordinate (p4);
\draw[help lines, <->] (p4) -- node[fill=white,text=black]{$f(x_{0} + \varepsilon)$} (p4 |- O);
\end{tikzpicture}
\end{document}
这给出了输出
动画显示了割线如何随着点的不同位置而变化问沿着固定的函数曲线,下面的代码应该提供一个起点。
\documentclass[tikz,border=3pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,calc}
\begin{document}
% create figures with different placement of Q along the function curve
\foreach \i in {0.45,0.46,...,0.72,0.71,0.70,...,0.46}{% <-- specify step
\begin{tikzpicture}[>=stealth',
dot/.style={circle,draw,fill=white,inner sep=0pt,minimum size=4pt}]
% draw axis lines
\draw[->,thick] (-0.5,0) -- ++(11,0) node[below left]{$x$};
\draw[->,thick] (0,-0.5) -- ++(0,7) node[below right]{$f(x)$};
\coordinate (O) at (0,0);
% create path for function curve
\path[thick,red] (-0.3,2) to[out=-25, in=200] coordinate[pos=0.2] (p) coordinate[pos=\i] (q) (9,5);
% fill area
\fill[blue, opacity=.1] (p) -| (q);
% draw the secant line with fixed length
\draw[shorten <=-1.5cm] (p) -- ($ (p)!7.5cm!(q) $) node[below right, pos=0.9]{Sekante};
% draw function curve
\draw[thick,red] (-0.3,2) to[out=-25, in=200] (9,5);
% draw all points
\node[dot,label={above:$P$}] (P) at (p) {};
\node[dot,label={above:$Q$}] (Q) at (q) {};
\node[dot] (p1) at (P |- O) {};
\node[dot] (p2) at (Q |- O) {};
\node[dot] (p3) at (P -| Q) {};
% draw lines between nodes and place text
\draw (P) -- node[left]{$f(x_{0})$} (p1) node[dot,label={below:$x_{0}$}]{};
\draw (p2) node[dot,label={below:$x_{0} + \varepsilon$}]{} -- (p3);
\path (p1) -- node[below]{$\varepsilon$} (p2);
% draw blue arrows between nodes
\draw[<->,blue,thick] (P) -- node[below]{$\varepsilon$} (p3);
\draw[<->,blue,thick] (Q) -- node[right]{$f(x_{0} + \varepsilon) - f(x_{0})$} (p3);
% draw the explanation for the y-value of point Q
\draw[help lines] (Q) -- (Q -| {(9.5,0)}) ++(-0.5,0) coordinate (p4);
\draw[help lines, <->] (p4) -- node[fill=white,text=black]{$f(x_{0} + \varepsilon)$} (p4 |- O);
\end{tikzpicture}
}
\end{document}
将输出 PDF 编译为 GIF(每帧 100 毫秒)后,结果如下
答案3
像往常一样,使用 PSTricks 只是为了好玩。
\documentclass[pstricks,border=12pt,12pt]{standalone}
\usepackage{pst-plot,pst-eucl}
\def\f{(x-1)^2/5+1}
\def\L#1#2#3{\psCoordinates[linestyle=dashed](#1)\uput[-90](#1|0,0){$#2\mathstrut$}\uput[180](0,0|#1){$#3$}}
\begin{document}
\begin{pspicture}[algebraic,saveNodeCoors,NodeCoorPrefix=N](-2,-1)(7,5)
\psaxes[labels=none,ticks=none]{->}(0,0)(-1,-1)(6.5,4.5)[$x$,0][$y$,90]
\psplot[linecolor=red]{-1}{5}{\f}
\pstGeonode[PosAngle=90](*1 {\f}){P}(*3.5 {\f}){Q}
\psdot(Q|P)
\pcline[nodesep=-2](P)(Q)
\L{P}{x}{f(x)}
\L{Q}{x+\varepsilon}{f(x+\varepsilon)}
\pcline[linecolor=blue](P)(Q|P)\nbput{$\varepsilon$}
\pcline[linecolor=blue](Q)(!NQx NPy)\naput{$f(x+\varepsilon)-f(x)$}
\uput[-45]([nodesep=-1]{p}Q){secant}
\uput[0](*5 {\f}){\textcolor{red}{$y=f(x)$}}
\end{pspicture}
\end{document}
答案4
MetaPost 和 Asymptote 也非常擅长这种绘图。这是使用 MetaFun 格式的 MetaPost 的尝试。我尝试尽可能地重现初始图片,并使其易于根据需要调整其参数化。它将被处理mpost --mem=metafun --tex=latex file.mp
(至少在 Unix 系统上)。
input latexmp; setupLaTeXMP(textextlabel=enable, mode=rerun);
vardef drawemptydot expr z =
save circle; path circle; circle = fullcircle scaled 3bp shifted z;
unfill circle;
draw circle;
enddef;
u := cm; % Unit length
beginfig(1);
xmin := -0.5; xmax := 9.5; ymin := -0.5; ymax := 6;
path curve; curve = (-0.5, 3.5){dir -30} .. (2.5, 2){dir 15} .. (5, 3.5) .. (8, 6){dir 30};
% Triangle and labels
z.P = point 1 of curve; z.Q = point 2 of curve;
z.R = (x.Q, y.P); z.S = (x.P, 0); z.T = (x.Q, 0);
fill z.P--z.Q--z.R--cycle scaled u withcolor 0.9[blue, white];
%
drawoptions(withcolor blue);
drawdblarrow (z.P -- z.R) scaled u shortened 2bp;
drawdblarrow (z.R -- z.Q) scaled u shortened 2bp;
label.bot("$\varepsilon$", u*.5[z.P, z.R]);
label.rt("$f(x_0+\varepsilon) - f(x_0)$", u*.5[z.R, z.Q]);
%
drawoptions(withcolor black);
draw ((x.P, 0) -- z.P) scaled u;
draw ((x.Q, 0) -- z.R) scaled u;
draw (z.Q -- (xmax, y.Q)) scaled u;
% The curve
draw curve scaled u withcolor red;
% Axes
drawarrow (xmin*u, 0) -- (xmax*u, 0);
drawarrow (0, ymin*u) -- (0, ymax*u);
label.bot("$x$", (xmax*u, 0));
label.lft("$f(x)$", (0, ymax*u));
% Other labels
label.ulft("$P$", u*z.P);
label.ulft("$Q$", u*z.Q);
label.bot("$x_0$", u*z.S);
label.bot("$x_0+\varepsilon$", u*z.T);
label.bot("$\varepsilon$", u*(.5(x.P+x.Q), 0));
label.lft("$f(x_0)$", u*(.5[z.S, z.P]));
z.U = (0.8[x.Q, xmax], y.Q);
drawdblarrow ((x.U, 0) -- z.U) scaled u shortened .5bp;
picture yQ_label; yQ_label = thelabel("$f(x_0+\varepsilon)$", u*.5[(x.U, 0), z.U]);
unfill bbox yQ_label; draw yQ_label;
% Secante
path secante; secante = 1.8[z.Q, z.P] -- 2.5[z.P, z.Q] ;
draw secante scaled u;
label.lrt("Sekante", u*point .9 of secante);
forsuffixes M = P, Q, R, S, T:
drawemptydot z.M scaled u;
endfor;
endfig;
end.