作者归档:隋辨

如何用互联网产品学习

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()
    

第 8 课 数据分析初步

讲的是利用Python进行数据控制、处理、整理、分析等方面的具体细节和基本要点。

  • 为什么是 Python 用于数据分析?

    1. Python 成功的部分原因是其能轻松地集成和调用 C、C++、Fortran 代码。大部分现代计算软件利用了一些 Fortran和 C 库来实现线性代数、积分、快速傅里叶变换等算法。许多企业和国家实验室也利用 Python 粘合来已经用了30多年的遗留软件系统。
    2. Python 和自然语言相似,很多科研人员和程序员非常喜欢,因此产生了第3点👇。
    3. Python 有很多高效、实用的类库,并可以方便地建立网站、爬取数据、数据分析、进行机器学习。
  • 库以及 pip 软件管理

    • library (类、库)是什么
    import time
    from time import sleep
    • pip 类库管理

    • pip 文档地址:https://pypi.org/project/pip/

    • 更换数据源:清华源地址

      • 升级 pip 到最新的版本 (>=10.0.0) 后进行配置:
      pip install pip -U
      pip config set global.index-url https://mirrors.cloud.tencent.com/pypi/simple/
      pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
      # 阿里源
      pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
      # 腾讯源
      pip config set global.index-url http://mirrors.cloud.tencent.com/pypi/simple
      # 豆瓣源
      pip config set global.index-url http://pypi.douban.com/simple/
    • 如果您到 pip 默认源的网络连接较差,临时使用本镜像站来升级 pip:

      pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip -U
    • 安装

      python -m pip install SomePackage            # latest version
      python -m pip install SomePackage==1.0.4     # specific version
      python -m pip install 'SomePackage>=1.0.4'     # minimum version
      # -m 的含义表示将库当作脚本来执行。
      pip install SomePackage            # latest version
      pip install SomePackage==1.0.4     # specific version
      pip install 'SomePackage>=1.0.4'     # minimum version
      pip freeze > requirements.txt
      pip install -r requirements.txt
      pip list  #   list installed packages
    • 卸载

      python -m pip uninstall SomePackage
    • 更新

      pip install package_name --upgrade
    • 科学计算的常用类库:

    • NumPy 是以矩阵为基础的数值计算模块,提供高性能的数组对象。文档地址:http://www.numpy.org/

    • Pandas 是基于 NumPy 的一种工具,纳入了一些标准的数据模型,提供了处理数字图表和时序数据的数据结构和操作功能,常用于金融数据分析。文档地址:https://pandas.pydata.org/

    • Scipy 是基于 NumPy 的一种高级数据处理工具,提供最优化、回归、插值、线性代数模块、傅里叶变换、信号和图像处理,常微分方程求解器等功能。文档地址:http://www.scipy.org/

    • Matplotlib 是2D绘图工具,常用于可视化展示数据。文档地址:http://matplotlib.org/

    • 其他类库

    • seaborn 是基于 Matplotlib 的更加美观的绘图工具。文档地址:https://seaborn.pydata.org/

    • anaconda 是科学计算常用的环境管理工具,什么是环境?

  • NumPy 初步

    • Python 自带的数据类型性能低。

    • jupyter 文档地址 pip install jupyterlab

    • 数据类型:ndarray

    • 特点:数组里面每一个元素是相同类型。

    • 手动创建数组

      import numpy as np    # 推荐如此导入Numpy
      vec = np.array([0, 1, 2, 3])
      mat = np.array([[0, 1, 2], [3, 4, 5]])
      mat.ndim
      mat.shape
      mat.dtype
      len(mat)    
    • 函数创建数组

      a = np.arange(9)
      b = np.arange(2, 2, 2)
  • 指定长度的数组

      c = np.linspace(1, 6, 6) 
  • 特殊的数组

      np.ones((2, 2)) # tuple
      np.eye(3) #   单位矩阵
      np.diag(np.array([1, 2, 3, 4]))   #   对角阵
      np.random.rand(4) #   随机数组
    
      np.random.seed(0)  # 设定随机种子,保证实验的可重现
      x1 = np.random.randint(10, size=6)  # 一维数组
      x2 = np.random.randint(10, size=(3, 4))  # 二维数组
      x3 = np.random.randint(10, size=(3, 4, 5))  # 三维数组
  • 内置数据类型

    • 明确定义数组数据类型:(默认数据类型是浮点型)
        tmp = np.array([1, 2, 3], dtype=float)
    • 所有内置类型
        f = np.array([1+2j, 3+4j, 5+6*1j])  #   j为虚部
        f.dtype
        b = np.array([True, False, False, True])
        s = np.array(['Bonjour', 'Hello', 'Hallo',])
        # int32
        # int64
        # uint32
        # uint64
    • 更多内容在下节

课后作业

  • 安装 pip 环境,和那几个数据分析库并且运行上述代码。

如何把自己送上火星

早在2014年,美国航天局(NASA)发起活动,邀请全世界的人提交他们的名字,乘客们将获得一张电子版的登机牌。当然,活动的名字是「把你的名字送上火星」,登记的名字将被存储到一个芯片里。

这是我去年拿到的太空登机牌。

BoardingPass_MyNameOnMars_Mars2020

上面写着,发射点是佛罗里达州卡纳维拉尔角,终点站是火星的耶泽罗撞击坑,运载火箭型号是擎天神5号。在三十天后,也就是2021年2月18日,毅力号火星车和机智号无人直升机将在火星着陆。机智号也是第一架在火星登陆的飞机。

截止到我写这篇文章的时候,中国共有41982人参与。打开网站,最好用电脑,目前还能参与:

https://mars.nasa.gov/mars2020/

你只需要填写你的名字、国家、邮箱,就可以获得你的登机牌,你的名字也将在30天后到达另一个6000万公里外的星星。

那个星球,遍布氧化铁构成的沙砾,因此呈现一片橘红。它没有大气层,如果我们在那,就可以清晰看见夜空中的星星。世界各地的名字以电子的形式,在元器件上构成一种独特的排列。毅力号带着它们,在红色大陆上,踽踽独行。多么凄美啊。

{31E04BAD-713F-40C5-B2BC-503DC94B3FEF}
mar4C8}
martests

「好奇号」传回的照片

第 7 课 面向对象的类设计

课程代码链接

  • 类设计

    • 参数传递

    • 作用域的实质

    • 内存绑定 : 如何编写带输出参数的函数(通过引用调用)?

    • 不可更改的类型 可以修改的类型
      string list
      tuple dict
      float
      int
      float
    • 保护数据

    • 私有属性 self.__name

    • 私有方法 self.__function_name()

    • 继承与多态

    • 理解为子承父业。

    • 父类(基类)和子类(派生类)

    • 覆盖方法

    • 多态:不同类型调用不同的实现。

  • dict 字典 {key: value}

    • dict_name [key] = value
    • del dict_name[key] dict_name.get()
    • dict_name[key] = value
    • dict_name[key]

第 6 课 类与数据结构

课程提纲

面向对象的类

  • 类(类型),是特殊的数据结构
  • 为什么要有类和对象?封装,把代码实现的细节覆盖。类就像一条生产线,就像一个完美模具。柏拉图的理型论认为:先有了这个理型世界,然后这个世界会按照这个完美的模子发展着。
  • 类设计:数据与行为(鸭子的模具,数据:声音、形状、颜色,行为:叫、游泳)
    • 方法:类中定义的函数。(鸭子的行为)
    • 对象:通过类定义的数据结构实例。(用模具创造一个鸭子)
    • 定义一个类(设计一个鸭子的模具)
    • class
    • def __init__
    • self 代表类的实例,而非类
    • 创建和使用
    • instance.method_name() instance.member
    • class_name.method_name() class_name.member

计算机领域的数据结构(了解即可):集合、数组、队列、栈、树、图等

  • 集合关系 set
    • 结构:元素无序地组织
    • 操作:{交、并、补 | 集合与集合之间}、{ 存、取、查找 | 集合内元素 }
    • 例子:是否有人迟到?
  • 线性结构,一对一,前驱后继关系
    • 列表
    • 队列(可用list实现),先进先出 queue
      • 结构:像排队一样
      • 操作:增add() 、删pop()
    • 栈(可用list实现),先进后出
      • 结构:像桶一样
      • 操作:增、删
  • 树状结构,一对多
    • 二叉树
      • 结构:像族谱图
      • 110511_WqcR_2348884
    • m叉树
  • 图状结构,多对多
      • 结构:像地图一样
      • 操作:增、删
  • 特殊的数据结构
    • 字典 dict

Python 中的数据结构

集合关系 set

  • 结构:元素无序地组织 \ 无重复元素
  • 操作:初始化 set() {}
    • 逻辑运算 not ==
    • add()
    • remove(key) clear() pop()
    • 改 不可改!
    • in
    • setA & setBsetA | setB 差集setA - setB 对等差分 setA ^ setB

课后作业

注:那个爬虫作业取消,感觉还是太难,爬虫代码在这:https://github.com/xrandx/Dating-with-python-this-winter/blob/master/douban_book.py (存在 bug:定位的逻辑不对,只能爬页数大于1且小于11的读书页面)

队列(queue)是一种先进先出(FIFO, First-In-First-Out)的、操作受限的线性表。在具体应用中通常用链表或者数组来实现。

队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行取出操作。队列的容量是它能容纳元素的多少,队列的大小是元素已经占用的空间多少。

请定义一个 Queue 类,基于 list 实现如下的方法:

    queue = Queue()
    queue.enqueue()  # 将任意对象从队尾入队
    queue.dequeue()  #  使队头对象出队
    queue.size()  # 返回队列的长度(int)
    queue.capcity() #   返回队列的容量(int)
    queue.is_full() #   队列是否已满(bool)
    queue.is_empty()    #   队列是否为空 (bool)