作者归档:隋辨

线性模型基础

线性回归

回归问题

之前我们说,当预测值为连续值时,称为“回归问题”,离散值时为“分类问题”。但回归是什么,为什么要叫回归?

线性回归问题就是试图学到一个线性模型尽可能准确地预测新样本的输出值。

输入单一属性的问题,比如通过年龄数据预测一个人身高,输入的属性只有一个,即年龄,往往我们会先得到一系列的有标记数据,例如:[15岁,170cm] …… [20岁,175cm]。

输入多属性的问题,比如预测一个人的收入,输入的属性值就不止一个了,例如:(学历,年龄,性别,颜值,身高,体重)–>15k。回归问题就是要根据这些属性,预测新样本中人的收入。

回归的来源:生物统计学家高尔顿研究父母身高和子女身高时的发现。父亲身高和儿子身高呈正相关关系。而在正相关关系背后还有另一个现象:矮个子父亲的儿子更可能比父亲高;而高个子父亲的儿子更可能比父亲矮。高尔顿对此研究后得出的解释是自然界有一种约束力,使人类身高在一定时期是相对稳定的。如果父母身高(或矮了),其子女比他们更高(矮),则人类身材将向高、矮两个极端分化。自然界不这样做,它让身高有一种回归到中心的作用。

他当时给出了一个回归的式子,y 和 x 分别代表以英寸为单位的子代和父代的身高:

y = 3.78+0.516 x

即使父母的身高都很高,其子女不见得会比父母高,而可能会衰退(regression)(回归)至平均身高的倾向。虽然之后的x 与 y 变量之间并不总是具有“衰退”(回归)关系,但是为了纪念高尔顿这位伟大的统计学家,“线性回归”这一名称就保留了下来。

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 20, 20)
y = 3.78+ 0.516 * x
trainning_set = y + np.random.randn(y.shape[-1]) * 2
plt.plot(x, trainning_set, 'gx')

coeff = np.polyfit(x, trainning_set, 1)
poly1 = np.polyval(coeff, x)
plt.plot(x, poly1, 'b')

plt.show()

线性模型假设

假设内容:输入变量 x 的各个属性(分量)在对应的输出变量 y 中有不同的权值,或者说,输入变量的各个分量的线性组合来拟合 y 值。

\mathbf{x} = (x_1, x_2, \cdots, x_n) 是一个实例, x_i 代表了实例在第 i 个属性上的取值。我们通常令 x_0 = 1

h(\mathbf{x})=\mathbf{w}^{T} \mathbf{x}=\sum_{i=0}^{n} w_{i} \cdot x_{i}

线性模型最大优点不是计算方便,而是易于解释。一些 SOTA(state of the art) 的模型里面也经常组合使用线性模型。

我们确定了模型假设,那么接下来就是确定模型的参数。

在训练集上确定系数 w_i 时,预测输出 h(x) 和真实输出 y 之间的误差是关注的核心指标。

image-20210310192643787

在线性回归中,我们常常以均方误差 (MSE) 来作为模型误差。当线性回归的模型为二维平面上的直线时,均方误差就是预测输出和真实输出之间的欧几里得距离,也就是向量长度( 或者说向量的 L2 范数)。而以使均方误差取得最小值为目标的模型求解方法就是最小二乘法。平方则是为了得到证书,因此它可以刻画样本点与直线之间的距离。

所以线性模型的泛化误差 E_{\mathrm{out}}(h) ,其中 (\mathbf{x}, y) 是未知的样本:

E_{\mathrm{out}}(h)=\mathbb{E}\left[(h(\mathbf{x}) - y)^{2}\right]

经验误差就是:

E_{\mathrm{in}}(h)=\frac{1}{N} \sum_{i=1}^{N}\left(h\left(\mathbf{x}_{i}\right) - y_{i}\right)^{2}

于是我们得到了最终目标 \mathbf{w}^*

\begin{array}{l}
\mathbf{w}^{*}=  \underset{\mathbf{w}}{\arg \min } E_{\mathrm{in}}(h)
\end{array}

式中每个 x_i 代表训练集中的一个样本。

求偏导以得出最值,粗体是向量或矩阵:

\begin{aligned}

E_\mathrm{in}(h) 
& = E_\mathrm{in}(\mathbf{w}) \\
& = \frac{1}{N}\sum^N_{i=1}(\mathbf{w^\top} \mathbf{x_i}  - {y_i})^2 \\
&=  \frac{1}{N}\sum^N_{i=1}(\mathbf{x_i^\top} \mathbf{w}   - {y_i})^2 \\
&=   \frac{1}{N} \left \|
\begin{aligned}
&\mathbf{x_1^\top} \mathbf{w} -   {y_1} \\
&\mathbf{x_2^\top} \mathbf{w} -   {y_2} \\
&\cdots \\
&\mathbf{x_N^\top} \mathbf{w} -   {y_N} \\
\end{aligned}
\right \| ^2 \\

&=   \frac{1}{N} \left \|
\begin{aligned}
\left [  \begin{aligned} \mathbf{x_1^\top} \\ \mathbf{x_2^\top} \\ \cdots \\ \mathbf{x_N^\top} \\ \end{aligned} \right ]  \mathbf{w} - 
\left [ \begin{aligned}  {y_1} \\ {y_2} \\ \cdots \\ {y_N} \\ \end{aligned} \right ] \end{aligned}
\right \| ^2 \\ 
& = \frac{1}{N}  \| \mathbf{X}\mathbf{w} - \mathbf{y} \| ^2

\end{aligned}

目标变成了:

\begin{aligned} 
\mathbf{w}^{*} &=\underset{\mathbf{w}}{\arg \min }  \frac{1}{N}  \| \mathbf{X}\mathbf{w} - \mathbf{y} \| ^2 \\
\\ &=\underset{\mathbf{w}}{\arg \min }   \frac{1}{N} \left(  \mathbf{w^\top} \mathbf{X^\top} \mathbf{X} \mathbf{w} - 2 \mathbf{w^\top} \mathbf{X^\top} \mathbf{y}  + \mathbf{y^\top}\mathbf{y}
\right)
\end{aligned}

求偏导:

\frac{\partial E_\mathrm{in}(\mathbf{w})} {\partial \mathbf{w}} = 
2 \mathbf{X^\top} \mathbf{X} \mathbf{w} - 2\mathbf{X^\top} \mathbf{y}

令其为0 ,考虑到矩阵不可逆(伪逆),得出:

\mathbf{w^*}  =  (\mathbf{X^\top} \mathbf{X} )^{-1} \mathbf{X^\top} \mathbf{y}
= X^\dagger \mathbf{y}

在单变量线性回归任务中,最小二乘法的作用就是找到一条直线,使所有样本到直线的欧式距离之和最小。说到这里,问题就来了:凭什么使均方误差最小化的参数就是和训练样本匹配的最优模型呢?

模型评估与选择(数据集构建)

机器学习过程

回顾高一的运动学实验,探索运动学公式:

x = \frac{1}{2}at^2

把带有滑轮的长木板平放在实验桌上,把滑轮伸出桌面,把打点计时器固定在长木板上没有滑轮的一端,并把打点计时器连接在电源上。此时 a = g = 10 m/s^2

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 20, 20)
y = 0.5 * 10 * (x**2)
trainning_set = y + np.random.randn(y.shape[-1]) * 2.5
plt.plot(x, trainning_set, 'gx')

plt.show()

png

训练集 X = \{(x_i, y_i)\} 这里等于 X = \{(0, 0), (1, 20.6), (3, 45.2), \cdots \}

测试集

假设空间:一元一次函数,一元 n 次函数,牛顿的假设-一元二次函数

def poly_format(coeff):
    fmt = ["%.2f" % (coeff[-1])]
    cnt = -1
    for i in reversed(coeff):
        cnt += 1
        if cnt == 0:
            continue
        fmt.append("%.2fx^%d + " % (i, cnt))
    fmt = reversed(fmt)
    return "".join(fmt)
coeff = np.polyfit(x, trainning_set, 2)
print(poly_format(coeff))

poly2 = np.polyval(coeff, x)
plt.plot(x, trainning_set, 'gx')
plt.plot(x, poly2, 'b')
plt.show()
5.01x^2 + -0.22x^1 + 0.64

png

coeff = np.polyfit(x, trainning_set, 1)
print(poly_format(coeff))
poly1 = np.polyval(coeff, x)
plt.plot(x, trainning_set, 'gx')
plt.plot(x, poly1, 'b')
plt.plot(x, test_set, 'rx')
plt.show()
100.03x^1 + -315.95

png

coeff = np.polyfit(x, trainning_set, 3)
print(poly_format(coeff))
poly1 = np.polyval(coeff, x)
plt.plot(x, trainning_set, 'gx')
plt.plot(x, poly1, 'b')
plt.plot(x, test_set, 'rx')

plt.show()
-0.00x^3 + 5.08x^2 + -0.73x^1 + 1.37

png

模型归纳偏好

特化与泛化

没有免费的午餐:https://www.leiphone.com/news/201907/jswawIEtorcAYvrB.html

奥卡姆剃刀原则:如无必要,勿增实体

误差

我们将学习器对样本的实际预测结果与样本的真实值之间的差异成为:误差(error)。

  • 在训练集上的误差称为训练误差(training error)或经验误差(empirical error)。
  • 在测试集上的误差称为测试误差(test error)。
  • 学习器在所有新样本上的误差称为泛化误差(generalization error)。

显然,我们希望得到的是在新样本上表现得很好的学习器,即泛化误差小的学习器。因此,我们应该让学习器尽可能地从训练集中学出普适性的“一般特征”,这样在遇到新样本时才能做出正确的判别。然而,当学习器把训练集学得“太好”的时候,即把一些训练样本的自身特点当做了普遍特征;同时也有学习能力不足的情况,即训练集的基本特征都没有学习出来。我们定义:

  • 学习能力过强,以至于把训练样本所包含的不太一般的特性都学到了,称为:过拟合(overfitting)。
  • 学习能太差,训练样本的一般性质尚未学好,称为:欠拟合(underfitting)。

训练集与测试集的构建方法

我们希望用一个“测试集”的“测试误差”来作为“泛化误差”(因为不可能知道)的近似,因此我们需要对初始数据集进行有效划分,划分出互斥的“训练集”和“测试集”。下面介绍几种常用的划分方法:

留出法

将数据集D划分为两个互斥的集合,一个作为训练集 S ,一个作为测试集 T ,满足 D=S∪TS∩T=∅

常见的划分为:大约2/3-4/5的样本用作训练,剩下的用作测试。需要注意的是:训练/测试集的划分要尽可能保持数据分布的一致性,以避免由于分布的差异引入额外的偏差,常见的做法是采取分层抽样。同时,由于划分的随机性,单次的留出法结果往往不够稳定,一般要采用若干次随机划分,重复实验取平均值的做法。

交叉验证法

将数据集 D 划分为两个互斥的集合,一个作为训练集 S ,一个作为测试集 T ,满足 D=S∪T且S∩T=∅ ,常见的划分为:大约 2/3-4/5 的样本用作训练,剩下的用作测试。需要注意的是:训练/测试集的划分要尽可能保持数据分布的一致性,以避免由于分布的差异引入额外的偏差,常见的做法是采取分层抽样。同时,由于划分的随机性,单次的留出法结果往往不够稳定,一般要采用若干次随机划分,重复实验取平均值的做法。

自助法

我们希望评估的是用整个D训练出的模型。但在留出法和交叉验证法中,由于保留了一部分样本用于测试,因此实际评估的模型所使用的训练集比D小,这必然会引入一些因训练样本规模不同而导致的估计偏差。留一法受训练样本规模变化的影响较小,但计算复杂度又太高了。“自助法”正是解决了这样的问题。

自助法的基本思想是:给定包含m个样本的数据集D,每次随机从D 中挑选一个样本,将其拷贝放入D’,然后再将该样本放回初始数据集D 中,使得该样本在下次采样时仍有可能被采到。重复执行m 次,就可以得到了包含m个样本的数据集D’。

调参

大多数学习算法都有些参数(parameter) 需要设定,参数配置不同,学得模型的性能往往有显著差别,这就是通常所说的"参数调节"或简称"调参" (parameter tuning)。

学习算法的很多参数是在实数范围内取值,因此,对每种参数取值都训练出模型来是不可行的。常用的做法是:对每个参数选定一个范围和步长λ,这样使得学习的过程变得可行。

ML1答案

  1. BCD
  2. 特征选择错了

答案可见 ML3 视频开头

机器学习入门

机器学习入门

课程纲要

什么是机器学习?

Improving some performance measure with experience computed from data.

机器从数据中总结经验。

什么时候用机器学习?

  • 事物存在某种潜在规律
  • 人不能直接发现这种规律 (例如牛顿定律)
  • 能获取大量数据

机器学习概念

  • 输入空间: \mathcal{X}
  • 输出空间: \mathcal{Y}
  • 假设空间( hypothesis space ): \mathcal{H} , 包含所有可能的 f :\mathcal{X} \mapsto \mathcal{Y}
  • 所有记录的集合:数据集, \mathcal{D}=\{\left(\mathbf {x_i},Y_i\right)|1\le i\le m\}
  • 一条记录( instance, sample ) \mathbf{x_i}
  • 数据的特征或者属性 feature, attribute : \mathbf{x_i} = \{x_1, x_2, \cdots, x_n \}
  • 训练集
  • 测试集

假设空间——机器学习的过程

new-pic-mine-e1572009324171

机器学习分类

  • 预测值为离散值或连续值的问题为:

    • 分类(classification)(上火问题,是否下雨)
    • 回归(regression) \mathcal{R}
  • 训练数据有标记信息的学习任务为:监督学习(supervised learning),分类和回归都属于监督学习。

  • 训练数据没有标记信息的学习任务为:无监督学习(unsupervised learning),常见的有聚类和关联规则。

  • 还有:batch learning, online learning, active learning, reinforcement Learning

为什么可以学习?

简要解释计算学习理论:

Ein(h)表示在训练集样本中,h(x)不与f(x)不相等的概率。即模型假设对样本(已知)的错误率。

Eout(h)表示实际所有样本中,h(x)与f(x)不相等的概率。即模型假设对真实情况(未知)的错误率。

霍夫丁不等式:

P[|\nu-\mu|>\epsilon] \leq 2 e^{-2 \epsilon^{2} N}

PAC

数据分析的一般流程

  • 数据清理和格式化
  • 探索性数据分析
  • 特征工程和特征选择
  • 基于性能指标比较几种机器学习模型
  • 对最佳模型执行超参数调整
  • 在测试集上评估最佳模型
  • 解释模型结果
  • 得出结论

13bb24f42e5bb98f4a9c15037e523d7d

作业

选择题

以下哪些问题适合用机器学习来解决?

A. 判断今年是闰年还是平年

B. 判断银行能不能给某人开信用卡

C. 判断北京明天的天气

D. 估计北京西直门早高峰的人流量

E. 计算地球运行的轨道

问答题

亚里士多德提出「物体下落的快慢是由物体本身的重量决定的」,他的错误出现在数据分析的哪一步?

我们的现代生活

dggggj

图片来自大咕咕咕鸡

谈到现代人,我们想到的是先进、文明,起码是刮胡子上班的男人,或者带妆约会的女人。谈到现代生活,我们想到的是阳光下玻璃幕墙包裹着写字楼,高楼里格子间的白领,周末人潮汹涌的影城、餐厅和商场。未来似乎永远会有更便宜好用的电子产品,摩尔定律永不失效,我们也将拥有比过去更优越的生活。然而这样的观念在整个人类历史中只占了四百年,在牛顿的自然哲学出现之前,人类观念和生活也全然不同。

人类如何走下无知舞台的?

文明万象更新,是从文艺复兴和宗教改革开始的。按韦伯的说法,人的思想开始祛魅——除去宗教神秘的色彩。

中世纪人的大多都有宗教信仰,工商业发展则顺理成章地让掌控民众思想的教会获取大量财产。自德国古腾堡发明印刷术,大多数信徒——无论是否有圣职,开始打破教会的垄断,独立阅读、解释圣经。当时神职人员在富裕条件下腐败不堪,经营酒店、赌场,公然售卖赎罪券,人们却得为教会各类仪式花钱,逐渐质疑教会权威。一众改革者,如马丁路德金,利用印刷术传播圣经及其解读,宣扬「人们可以自己与上帝对话,无需教会充当中介」。政治与教会有千丝万缕的联系,信仰问题常常会演变成政治问题。教会代表参加议会,政治领袖介入宗教事务,为他们建立教堂、修道院。一个出名例子是,因为离婚需要教宗允许,英国亨利八世为了离婚再娶,宣布脱离罗马教会而后盎格鲁宗成立 : )

不满的民众和当权者着手改革宗教体制,打破罗马天主教会一家独大的局面,其分裂出新教会和清教徒,改革了宗教观念——和上帝进行精神交流之时,人人独立平等。西方信仰统一的时代结束了,唯一的真理结束了,尤其是神学中的等级机制也结束了。

在很长一段时间,文艺复兴这场学术运动并不反对基督教,相反,许多伟大作品都是以宗教为主题的,而且得到了教会的赞许。但它也不是简单地恢复古希腊经典,而是借古讽今,批判社会制度体系。这就促使了后续物理、数学、地理大发现等方面发展。

但科学认识发展并不一定导致上帝黄昏。韦伯认为,现代的理性主义发源于英国加尔文教的清教徒。宗教观念由另一个宗教观念终止。

当时公共领域盛行的观念——财富本身非常危险。清教徒有禁欲主义的的职业观,他们反对寻欢作乐、虚掷光阴、好逸恶劳,认为感官享乐是清教的最大敌人。如何抵制和扫除世俗快乐,如何受到上帝恩典?唯有凭借日常生活中的艰苦劳动。西方盛行的禁欲主义蔓延到社会的方方面面,同样也改变公众对于财富的态度:我们要避免的是财富享受及其随之而来的怠惰和肉欲,否则财富会让人远离上帝。为了上帝的荣耀,他们只储存财富,或合理用于个人与公众,但不能为肉体冲动而挥霍一空。要节约时间,刻苦劳动,并且要有谋略、聪明地劳动。劳动是抵制诱惑、爱欲和享乐的唯一手段,并不是为积累财富,而是生活目的所在。

新的金钱概念消除公众对于财富的罪恶感,而商人在世俗生活中利用这种观念是使牟利正当化,心安理得地享受物质。清教徒的禁欲精神则演变为了现代工人的安分守己。现在还能发现企业家精神就是清教徒精神的新版本,时常也能看见一种精神遗迹——打工人就是要守本分。

劳动观念的变革,将禁欲主义的理性,有目的的理性赋予资本主义。现代社会的基础设施——效率和功能至上法律和制度,就从这种理性生长而来。清教徒的理性,是一个人所作所为必须符合某种目的,以期达到某种可想而知的后果。比如,人们开办学校,是为了学好知识,相信有知识就有光明未来的价值观念,称作价值理性。学校目的是让学生掌握知识,成为有价值的人,最终学校极为理性地设置了本科升学率、成绩排名、班级排名等等,开设了早晚自习、课间操。为了班级成绩排名,理性的老师让他们取消体育课和艺术课,布置良多作业,设班长来消除影响纪律的因素。学生为了能登上年级前几名,熬夜学习,课间也不休息。不为求知,而为其指标努力,就是形式理性。有人天生早起精力不足,被要求早上七点开始早读和跑步;有人不习惯长时间静坐,需要在学校坐上十二个小时;有人为了获得复习时间,输营养液来避免去食堂吃饭。形式上的理性,就会达到真正目的吗?

指标、制度变成了系统中各个部件的目标,人们忘记了最初目的是掌握知识,而非提高成绩。形式合乎理性不意味着实质理性。市场契约、国家法律,乃至现代大大小小的组织制度,都与学校的规章、课堂的纪律类似,最终会偏离真正目的。毕竟人是复杂的,制度是简单的。这样的现象也成为了现代社会日常,有白领上班年薪几十万猝死在凌晨的街头,有富豪因债务抛妻弃子跳楼自杀,有城市中产天天为孩子学习失眠。

在资本主义之前的经济生活中,一切生产都是粗糙的。欧洲中世纪到处都是庄园,领主掌握着一切。中国大部分田地,由地主乡绅控制。他们都具备宗法性质,自给自足,不追逐利润也不需要市场。在马克思那里,自由劳动者的土地和劳动工具被剥夺,他们只剩下劳动力可以出售。在丢弃掉禁欲主义的理性下,人们创造出专业化的职位、自由的市场、科学的管理制度…… 劳动者离开故乡,成为流动的市场要素,资本家将他们集中在一起,生产资料得以在某地集中变成商品。

工业主义打破了原本静谧美好的田园生活,人与人的关系原本是长久而稳定的,一个人的生活半径不过是出生地,或邻边的村庄。社会事务的规则一般由领主或宗主决定,是腐朽而封建的。随后机器消灭了这些关系,人们进入陌生地区谋生变为常态,领主不再,宗族规范失效,村口张大妈的碎嘴也听不见了。道德对人不再有如此强势的约束力,原子化的人即使破坏道德,只消换个城市又是一个新人。

为了满足生活需要,人们逐渐建设了更专业化的服务设施,通常把这些设施集中的地方叫做「城市」。为了解决不同阶级之间的纠纷,人们创造出现代化的「法律」、「监狱」。为了粘合异乡人与本地人的感情,缓和矛盾,人们发展出了「民族主义」。「现代」国家的雏形逐渐显现。

祛除封建、迷信、神性,理性却勾勒出了现代化的牢笼:人们需要好好读书,像清教徒一样工作,娶妻,买个大house,养条金毛、英短。一切理性工作,为成为更好的螺丝钉,于是很多职业不再与人们产生联系,不再给人意义感。韦伯阐述资本主义现代性悖论——现代社会以理性的方式推动物的进步,但物反过来非理性地控制着人。人们和他们生活中的一切都那么远,和他们的国家、社区、亲戚,和他们的工作、学习,为了更好的生活,将社会生活规约于形式,最后在社会机器中失去真实的自由。


test

如何用互联网产品学习

kelly-sikkema-Oz_J_FXKvIs-unsplash

Photo by Kelly Sikkema on Unsplash

互联网只完成了最初使命的百分之三十。

一文中,讨论了互联网最初的设想:我们能极为方便地在互联网上跳转,我们一天接收的文字、视频,其信息量就能超过苏格拉底与他人的对话。但现在,互联网企业因河为池,逐渐局域化。即便那局限的互联网,也是一条污浊的泥河,仍需要借助数学模型才能捞到河底金砂。人们设想 memex 这样的机器,原初目的大致是学习知识,并且人类会因为知识而改善生活。

现在并不存在那样的产品——一个能解答任意问题来改善生活的产品。人类有强悍的谷歌,有丰富的维基,有各式的问答网站,有足以存储无限知识的笔记软件。即便生活在比苏格拉底更能轻易获得知识的时代,却未必有他的智慧。是这些知识没有作用,还是说人们根本没有学习?

很多时候,人们总说,「明白很多道理却依然过不好这一生」。我们真明白很多道理?答案并非肯定。我所知道的是,我们时常把信息当作知识,经常把收藏当作学习,习惯把阅读当作思考,常常把存储当作掌握。知识就是力量,法国就是培根 :),没有谁不知道知识与关键信息多重要。关键是,用什么方法或工具去学习互联网上的知识?

要理解学习,先理解大脑。大脑将信息存储在工作记忆,经过重复、联想等记忆方法,变成长时记忆,形成牢固的组块。

什么是组块?神经科学认为组块 (Chunk) 的本质是由于意义联系或反复使用而形成的神经回路。比如儿童开始学习英文字母,先记住 a 的形状和读音,大量背诵之后,形成长时记忆中一个组块。当所有字母已经组块化,不再是认知负担 (Cognitive Load) ,开始学习单词,大脑开始熟悉 a-p-p-l-e 的拼写和读音,将单词组块化。下一个就是词组和意群,然后是长难句。大脑是这样利用组块去降低认知负担和学习难度。

一个人工作记忆(瞬时记忆)中只能短暂地存储 2 ~ 4 个组块,所以我们常常按照分段的方法 139-XXXX-XXXX 来记忆电话号码。大脑分而治之,将信息拆分成有意义的组块,更利于记忆。这 2 ~ 4 个组块大小的工作记忆,在幼儿园小孩那里能放下几个字母,在小学生能存储几个短语,在高中生那里可以留下一些句子。工作记忆的容量是天生的,但长时记忆中的组块不是。你拥有的组块越多,就越能在瞬时记忆中记下更多东西,也就是说,你记忆信息越多,越容易记住与其相关的信息。

记忆不等同于学习,但它是学习的基础。大脑掌握了相当多的组块,一方面便于学习新概念,另一方面大脑进入发散状态时,能将不同区域的组块联系在一起形成新思想,也就是我们常说的想象力、创造力、融会贯通……知识成为组块,再经过发散或者专注的思维,人们得以解决此前从未遇到的问题。这才是学习的意义。

学习的大部分时间都应该用在组块化上。加速组块化的基本方法是回想 (Recall) 和间歇性重复。我们背诵、默写、考试、用费曼学习法等来学习知识,本质上都是在以不同的形式,依靠少量的线索重新激活组块。如果只是重复地阅读材料,依据材料画思维导图,效率比回想低,除非是间歇性地多次重复此类方法。这里能发现,大脑越觉得学习方法费劲,越容易加强记忆。

如果我们只是在网上不断浏览文章、观看视频,大多数知识都不会变成组块,而是被大脑修剪、代谢。事无巨细地存储知识和信息,是一种囤积癖。那些东西躺在那里,只是你再也想不起来,那有什么意义呢?

一个真正的 memex 是什么样的?它一方面应当提供个性化的、易于组块化的知识,一方面要具备对信息的索引功能。前者是因为机制必须促使人回想和重复,才能更易于记忆。于是互联网涌现出百词斩、扇贝、Anki 这样的抽认卡软件,其通过「间歇性重复」、「意义联系」达到组块化。博客、微博和公众号如果善加利用,经过总结输出也能实现「回想」的效果。后者是因为并非所有信息都应该被记住(比如某个国家人均 GDP),需要记住的是知识背后的逻辑(GDP能反映的现象,该国家有哪些因素促成了目前的经济状况,GDP与其经济状况的关系……),所以只需通过索引找到那些信息。因此出现了印象笔记、Onenote、Pocket 这类能存储网页的产品。这样的笔记产品容易使人患上「囤积癖」,存储几千条笔记,放在那却不会再看第二次,最终海量无用的信息淹没真正重要的知识,活脱一现代的「买书如山倒,看书如抽丝」。

之前笔记软件 Notion 火了一阵子,Notion 的目标并不是学习,重结构,重形式,把超链接和数据库的模型下放到产品。问题是结构调整很多时候只是另一种形式的思维导图而已。大脑由神经网络组成,擅长捕捉相关性,如果让你想象与锚、水手、锅炉相关的名词,你大概会想到轮船、海洋之类。这些组块相互联系,一个组块激活之后会激活相关组块。大脑更容易记住网络结构的信息?这种论断没有经过试验,就好比说吃核桃补脑。notion 更像一个简易网页设计工具,让普通人也能设计出不错的网页,也许是方便团队协作吧。

所以我要在这里向你介绍 flomo ,它的电脑端界面如下图:

image-20210207202200242

为什么我要推荐它?

  1. 降低输出笔记的心理负担。你可以通过微信服务号发送你的笔记,也可以通过电脑、手机浏览器访问。你会发现网页长得和微博一样,却不需要面临被人评论的压力,可以直接通过文本框输入信息,从打开到输入变成了零距离。
  2. 成就反馈。左上角是像 Github 一样的贡献墙设计,能让你直观地知道自己输出了多少。同时在首页就能看见过往的笔记和标签,这也是一种反馈。
  3. 回想。 flomo 不提倡网页剪藏,哪怕是网上容易复制的文本,用户最好还是自己输入笔记。同时,你可以有意识地将知识分割成组块,并设置一些标签。这样,输出过程成为了大脑回想的过程,提升了组块化的效率。
  4. 重复。你会发现其专业版有「随机漫步」、「每日回顾」功能。前者会随机聚集内容将你没有设置过的标签挖掘出来,让你以另一种分类和视角看待标签下的内容;后者是你设置一个定时器,它就会按时通过微信服务号,将你设定的相关标签下的内容发送到你微信。前者把不同知识组块联系在一起,后者实现大脑对知识的间歇性重复,使得大脑中已有组块更加牢固。

image-20210207203632218

由于这四个优点,相比于其他笔记产品, flomo 成为了我心里更接近完美的作品。它简洁、美观、轻量化,会让人爱上做笔记。相信我,即便你从来没有记笔记的兴趣,也会在这个产品里养成通过输出思考的习惯。

第 10 课 NumPy 计算和广播原理

前情提要

第 9 课补

  • arr[2, :]

  • np.ix_()

    import numpy as np
    
    arr2 = np.arange(32).reshape((8,4))
    print(arr2)
    
    arr2[np.ix_([1,5,7,2],[0,3,1,2])]
    
    arr2[np.ix_([1,5,7,2],[0,1,2])]

第 9 课答案

    1. numpy.random.randint

      np.random.seed(3)
      x1 = np.random.randint(low=1, high=10, size=100)
      np.save("save.npy", x1)
      
      x1 = np.load("save.npy")
      print(x1)

课程纲要

  • 数学计算

    • 逻辑运算np.where np.all() np.any()
    arr = np.random.rand(2, 3)
    result = np.where(arr > 0.5, 1, 0)
    #   condition ? arr1: arr2
    arr = np.random.rand(2, 3)
    result = np.all(arr > 0.1)
    arr = np.array([2, 2, 3, 3, 1])
    result = np.unique(arr)
    • 线性代数:numpy.linalg 库文档

    • np.trace np.inner()

    • linalg.qr linalg.svd

      arr = np.array([[2, 2, 3, 3], [4, 3, 2, 1]])
      U, s, V = np.linalg.svd(arr)
    • 统计运算

    • 求和 arr.sum(axis=0)

      arr = np.random.rand(2, 3)
      result = np.sum(arr)
      
      result = np.sum(arr > 0.5)    #   根据条件求真值的和
    • 最值 arr.max() arr.min() arr.argmin() arr.argmax() 文档

      arr = np.random.rand(2, 3)
      result = np.max(arr)
      
      arr = np.random.rand(2, 3)
      result = np.argmin(arr)
    • 算术平均数 np.mean()

      arr = np.random.rand(2, 3)
      result = np.mean(arr)
    • 标准差、方差 np.std() np.var()

  • Numpy 的形状操作

    • 添加维度
    arr = np.array([1, 2, 3])
    result = arr[np.newaxis, :, ]
    print(arr)
    print(result)
    • 改变维度个数和大小 np.resize() np.reshape() ,前者改变源数组,后者不会。
    arr = np.random.random((4, 4))
    print(arr)
    arr.resize((2, 3))
    print(arr)
    arr.resize((1))
    print(arr)
  • NumPy 的广播原理

    • 维度和维度大小

    • 广播(broadcasting)

    • 什么是广播

      arr = np.ones((2, 4))
      arr2 = 1
      print(arr)
      print(arr2)
      print(arr + arr2)
    • 规则1:数组维度和大小,从后往前有连续的相同部分

      arr = np.ones((2, 4, 4))
      arr2 = np.ones((4, 4))
    • 规则2:不相同的部分维度大小为1

      arr = np.zeros((2, 4, 4))
      arr2 = np.ones((1, 1))
  • Matplotlib

    • 画一个三角函数吧
    import numpy as np
    import matplotlib.pyplot as plt
    
    X = np.linspace(-np.pi, np.pi, 100)
    COS, SIN = np.cos(X), np.sin(X)
    ax = np.zeros(100)
    plt.plot(COS)
    plt.plot(SIN)
    plt.plot(ax)
    plt.show()