预测的 KPI:RMSE、MAE、MAPE 和 Bias
Nicolas Vandeput 发布在 Towards Data Science 上的文章,同时也是其著作《Data Science for Supply Chain Forecasting》中的一章。
为预测任务挑选一个合适的指标并没有想象中那么简单,所以这次我们来研究一下 RMSE、MAE、MAPE 和 Bias 的优缺点。剧透:MAPE 是其中最差的,别用。
Nicolas Vandeput 发布在 Towards Data Science 上的文章,同时也是其著作《Data Science for Supply Chain Forecasting》中的一章。
为预测任务挑选一个合适的指标并没有想象中那么简单,所以这次我们来研究一下 RMSE、MAE、MAPE 和 Bias 的优缺点。剧透:MAPE 是其中最差的,别用。
这回来介绍一下如何利用管道(pipe)风格将 Pandas 相关的代码写得更易读,不过首先让我们看看隔壁 R 语言中管道是怎么用的。假设输入是 x
,经过连续四个函数的处理后得到输出 y
,代码可以按顺序写:
x1 <- func1(x, arg1)
x2 <- func2(x1, arg2)
x3 <- func3(x2, arg3)
y <- func4(x3, arg4)
相信大伙对 NumPy 和 SciPy 里的插值比较熟:已知坐标值 xp
和变量值 fp
,调用函数计算变量在目标坐标 x
上的数值。例如 np.interp
的 API 就是
np.interp(x, xp, fp)
Pandas 的 Series
和 DataFrame
对象也有插值方法 interpolate
,默认做线性插值。但其功能与 NumPy 和 SciPy 不太一样。以一个序列对象 s
为例:
# 缺测部分和有效部分.
invalid = s.isna()
valid = ~invalid
# 对应于xp.
s.index[valid]
# 对应于fp.
s.values[valid]
# 对应于x.
s.index
# 两式大致等价.
s.interpolate(method='index').values
np.interp(s.index, s.index[valid], s.values[valid])
即 Pandas 的插值是要利用序列的有效值当 xp
和 fp
,去填补缺测的部分。所以调用 s.interpolate
时我们不需要传入形如 x
的参数,而是应该在调用前就通过 s.reindex
之类的方法将 x
融合到 s
的索引中。这么说可能有点抽象,下面就以图像直观展示 Pandas 里插值的效果。本文不会涉及到具体的插值算法(最邻近、三次样条……),仅以线性插值为例。
Python 的取模运算 r = m % n
相当于
# 或q = math.floor(m / n)
q = m // n
r = m - q * n
即取模的结果是被除数减去地板除的商和除数的乘积,这一规则对正数、负数乃至浮点数皆适用。
当 n
为正数时。显然任意实数 x
可以表示为 x = r + k * n
,其中 0 <= r < n
,k
是某个整数。那么有
x // n = floor(r/n + k) = k
x % n = x - x // n = r
即 x % n
的结果总是一个大小在 [0, n)
之间的实数 r
。当 n = 10
时,以 x = 12
和 x = -12
为例:
如果以 n
为一个周期,那么 x = 12
就相当于往右一个周期再走 2 格,x % n
会消去这个周期,剩下不满一个周期的 2;x = -12
相当于往左两个周期后再往右走 8 格,x % n
会消去这两个周期,剩下不满一个周期且为正数的 8。
再本质点说,取模运算就是在 [0, 10)
的窗口内进行“衔尾蛇”移动:
12
向右超出窗口两格, 12 % 10 = 2
,即右边出两格那就左边进两格。-12
向左超出窗口 12 格,-12 % n = 8
,即左边出 12 格那就右边进 12 格,发现还是超出左边两格,再从右边进两格,最后距离零点 8 格。
最近学习用 PyTorch 做时间序列预测,发现只有 TensorFlow 官网的教程 把时间窗口的选取和模型的设置讲得直观易懂,故改编如下。本人也只是入门水平,翻译错误之处还请指正。
本文是利用深度学习做时间序列预测的入门教程,用到的模型包括卷积神经网络(CNN)和循环神经网络(RNN)。全文分为两大部分,又可以细分为:
本文用到的数据和 notebook 可以在 GitHub 仓库 找到。
这是物理海洋学家 Ken Hughes 在 2021 年发表的博客文章,原文标题为 A better way to code up scientific figures。以 Matplotlib 和 Matlab 为例,强调了模块化思想对于科研作图代码的帮助。我很少看到关于作图方法论的文章,所以翻译出来交流学习。
我画一张出版级别的科研配图一般需要写 100 - 200 行代码,这个长度有点点危险,因为很容易写出能正常运行但又一团糟的东西。如果代码片段都很短还可以从头重写,但如果代码有上千行,提前做好规划会更明智一些。不过在这两种极端情况之间潜藏着另一种吸引人的做法:写出一段当时感觉无比连贯,但以后会让你吃苦头的脚本。
假设你想画一张中等复杂度的图片,类似下面这张:
说到测量程序的运行时间这件事,我最早的做法是在桌上摆个手机,打开秒表应用,右手在命令行里敲回车的同时左手启动秒表,看屏幕上程序跑完后再马上按停秒表,最后在纸上记下时间。后来我在 Linux 上学会了在命令开头添加一个 time
,终于摆脱了手动计时的原始操作。这次就想总结一下迄今为止我用过的那些测量时间的工具/代码。
二维平面上一系列点的坐标由 x
和 y
数组描述,同时准备一个形状相同的 mask
数组。若第 i
个点落入了平面上一个多边形的内部,则令 mask[i] = True
;若在多边形外,则令 mask[i] = False
。由此得到的 mask
数组即掩膜(mask)数组,它可以作为布尔索引分出多边形内外的点
x_in, y_in = x[mask], y[mask]
x_out, y_out = x[mask], y[mask]
它可以作为掩膜,掩盖多边形范围外的值——即把外面的值设为 NaN,以便进行后续的计算
z[~mask] = np.nan
z_mean = np.nanmean(z)
下图展示了两个应用:左小图的多边形是一个中心带洞的正方形,给定一系列散点的坐标,计算出掩膜后可以把多边形内的散点画成红色,多边形外的散点画成蓝色;右小图的多边形是中国全域,给定 (50, 50)
形状的经纬度网格,计算出掩膜后用橙色画出掩膜为 True
的部分,这张掩膜之后可以用来处理网格上的其它变量。
本文的目的是介绍如何用 Python 制作掩膜数组,并尽量优化其运行时间。从 shapefile 中读取中国国界并转化为 Shapely 中的多边形对象等操作,已经在博文 Cartopy 系列:探索 shapefile 中详细介绍过了,本文是对其的一个补充。
Cartopy 可以通过 feature
模块向地图添加国界 BORDER
和省界 STATES
,因其底层采用的 Natural Earth 地图数据并不符合我国的政治主张,所以我们经常需要自备 shapefile 文件来画中国省界,以下面的代码为例
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.io.shapereader as shpreader
extents = [70, 140, 0, 60]
crs = ccrs.PlateCarree()
fig = plt.figure()
ax = fig.add_subplot(111, projection=crs)
ax.set_extent(extents, crs)
filepath = './data/bou2_4/bou2_4p.shp'
reader = shpreader.Reader(filepath)
geoms = reader.geometries()
ax.add_geometries(geoms, crs, lw=0.5, fc='none')
reader.close()
plt.show()
图就不放了,这段代码足以应付大部分需要画省界的情况。然而我在无脑粘贴代码的过程中逐渐产生了疑惑:为什么 shapefile 会由三个文件组成?省界是以何种形式存储在文件中?Cartopy 和 Matplotlib 又是怎样将省界画出来的?调查一番源码后总结出了这段代码底层实现的流程:
本文的目的即是从头到尾解说一下这段流程,希望加深对 shapefile 格式,Matplotlib 和 Cartopy 包的理解。令人意外的是,随着探索的不断深入,我发现自己自然而然地学会了如何实现省份填色、省份合并,地图白化等,以前看起来十分困难的操作。本文也会一并介绍这些应用。
前段时间重看自己的文章时发现公式渲染、图片的放大缩小和代码高亮等功能都失效了,按 F12 发现原因是引自 cdn.jsdelivr.net
的字体资源、CSS 和 JS 文件都无法访问,挂梯子后页面恢复正常。