本来应该接着讲离散系统的混沌现象,但在这之前势必要讲动力学系统的临界现象和分岔,而分岔指的就是动力学系统相图的分岔
动力学系统 相图 (phase diagram) 的定义一句话可以说完:
相图是以动力学系统的驻点为因变量,参数为自变量的函数图像。
但这要求读者清楚 因变量 (dependent variable)、自变量 (independent variable)、参数 (parameter) 等等概念。现在是人工智能的时代了,还有个 超参数 (hyperparameter) 的概念也经常被人提起。
它们统统依附于“函数 (function)”这一概念。
函数/映射
戈德门特《代数学教程》(高教社版):
设 X 和 Y 是两个集合,称令 X 中的每一个元素 x 对应 Y 的一个[按一个确定的规律依赖 x 的]元素 y 的运算为定义在集合 X 上在 Y 内取值的函数。
括号是我自己加的,不加简直可以拿去考语文阅读理解,整本书的翻译都有这个问题。
简而言之,函数是一种运算。
以上定义是戈德门特《代数学教程》中批评的靶子,罪名是“包含数学上未曾定义过的词汇,例如‘令……对应’意指什么?轻信这个定义,就会又一次仅仅得到一个文字游戏”。然后给出了一个花了一节半内容铺垫的,完全基于集合论的定义。
数学家眼中的 bug,在科学家眼中简直是 feature。数学上未曾定义过的概念,在日常用语中往往有约定俗成的语义,科学要用的数学太多太杂了,辩经的功夫能省一点是一点吧~
写这篇文章的时候回去查了一下现在的中学课本,函数的定义出现过两次:
- 人教版八年级下册,甚至早于集合的定义,直接把函数定义成了变量 y 而非运算 f;
- 人教版高中必修一,和上面被批判的定义类似,但是限定了 X 和 Y 都是实数集。
我记得我们那时候课本上还有个映射 (mapping) 的概念,定义和函数很像,就是把里面的“数集”换成了任意对象的集合。这次查课本的时候没找到这个概念。
这很正常,“数”已经不再是现代数学的一等公民了,集合才是。既然没了特殊性,今天绝大多数语境下都不再强调函数和映射的区别,两者往往互换使用。
自变量、函数值、因变量
- 在函数的出发集 X 中取值的变量 x 叫做自变量
- 变量 x 的任意一个取值带入函数 f 计算所得的结果 f(x) 叫做函数值
- X 内所有 x 计算得到的 f(x) 也可以组成一个集合,在此集合中取值的变量叫做因变量
从自然科学的角度
按照大义名分——
- 因变量是人们感兴趣的变量,是科学试图解释的目标;
- 函数是科学为了定量地解释因变量而提出的数学模型;
- 自变量是这个模型为了解释因变量而需要的来自现实的信息。
对于学术民工,函数是饭碗,变量是合作组送来的数据,择其最容易凑出结果者为因变量,余者为自变量~
说正经的,科学中的函数值和因变量也还是有区别。
因为因变量和自变量一样都是由实验测量得到的,来自物质世界,测量的误差不可避免;
而函数是人对客观世界的一种认识,存在于观念/理性世界。
因变量和函数值之间,按照误差分析的规范,以“无法断言它们不相等”而相等,或者说拟合。
从编程的角度(以 python 为例)
编程中,因变量和函数值的区别之前略微谈过了,前者是左值,后者是右值。
以本系列第 4 篇提到的洛伦兹系统为例:
import numpy as np
def chaotic_derivative(x,y,z)
fx = 10*(y - x)
fy = 26*x - y - x*z
fz = x*y - (8/3)*z
return fx,fy,fz
dt = 1E-4
N = int(2.5E5)
XYZ = np.empty((3,N+1))
XYZ[:,0] = np.array([-10.0, -10.0, 20.0])
for t in range(N):
XYZ[:,t+1] = XYZ[:,t] + chaotic_derivative(*XYZ[:,t])*dt
这里不加解释地用了一个多自变量的函数。既然数/标量相对于其他数学对象并没有特殊性,那么一个有序数组/向量自然也可以做自变量,只要我们约定好向量各分量的顺序和含义。
自变量 vs. 参数
上一节的例子里,为了得到函数值,除了自变量之外,还有 10, 26, 8/3 之类的常数也参与计算。
这些自变量以外,在当下的函数中不变的数,也可以看作某些变量的特定取值 ,这些变量叫做函数的参数。
从应用数学的角度来讲,
- 自变量 取不同的值时,函数一直是那个函数,是同一个对应关系/计算方法 ;
- 参数 取不同的值时,原函数本身会变换成另一个函数,它们整体组成一个以参数(的所有可能取值)为指标集的函数族 。
从纯数学的角度来讲,参数只是一种特殊的自变量,参数的作用和自变量没有区别;
- 自变量出现在函数的表达式中,自变量的变化会导致函数值的变化;
- 参数也出现在函数的表达式中,参数的变化也会导致函数值的变化——
和 的具体表达式是完全相同的。
很多物理老师的幻灯片、讲义,乃至教材让人看不懂,很多时候都是因为数学记号的书写问题,同一对象的表示法前后不统一、同一符号指代的对象前后不统一、统一但是有歧义又没说明……
从自然科学的角度
因为实验仪器和实验方法是有限的,所以能拿到的实验数据类型是有限的。
- 自变量 是实验科学家能够通过实验观测取得数据的变量,也就是模型的用户输入。
- 参数 是理论科学家选定一个函数族之后,为了让函数值拟合因变量,而在模型内部调整的变量,对用户屏蔽。
自变量和参数概念的分离,体现的是科学中,实验和理论的分工和解耦。
实验设计
最近看一些实验方向的招聘启事,岗位要求里经常有“能够进行/熟练掌握/精通实验设计”之类的说法。所谓实验设计,目的就是验证已有的理论模型和参数的选择是否正确。
方法是寻找一个新的实验和对应的函数,让旧函数的参数,恰好是新函数的自变量。这样新实验的数据作为自变量代入新函数,和新的因变量进行比较,就可以在实验上验证旧函数和旧参数的正确性。
当旧参数/新自变量的取值只有“是/否”这一对逻辑值时,实验设计就简化回了生命科学里常见的“假设检验法”;
反过来就是“假设检验法”在物理、化学中见得少的原因——那些学科的的定量程度更高,实数集 的元素有无穷多,而区区 1024 个可能取值的一个变量,就需要 10 个二进制位编码,也就等价于要设计 10 个待检验假设。
物质科学里,很多情况下是先有一套先进实验设备,低温、高压、强磁场……有啥锤子就敲啥钉子,不说了不说了,再说号没了。
从编程的角度(以 python 为例)
python 中的函数,不仅可以像前一节那样直接定义,也可以实例化一个定义了 __call__()
方法的 class。这里就能体现出参数和自变量的区别了——
import numpy as np
class LorenzDerivative(object):
def __init__(sigma,b,r):
self.sigma = sigma
self.b = b
self.r = r
def __call__(x,y,z):
fx = self.sigma*(y - x)
fy = self.r*x - y - x*z
fz = x*y - self.b*z
return np.array([fx,fy,fz])
chaotic_derivative = LorenzDerivative(sigma=10,b=8/3,r=26)
dt = 1E-4
N = int(2.5E5)
XYZ = np.empty((3,N+1))
XYZ[:,0] = np.array([-10.0, -10.0, 20.0])
for t in range(N):
XYZ[:,t+1] = XYZ[:,t] + chaotic_derivative(*XYZ[:,t])*dt
参数 是 __init__()
方法的输入;
自变量 是 __call__()
方法的输入。
超参数
前文所述理论科学工作的本质,
就是向实验科学交付以部分实验数据为自变量,其余数据为因变量的函数;
交付格式就是函数族的表达式,以及其中参数的取值。
其中的函数族是从各学科公理和定理出发,推导出来的特定算法,参数往往也是“客观”存在的物理量,具体问题具体分析。
而机器学习/人工智能 (ML/AI),则是预先想定若干参数量极大的通用函数族,利用超多参数带来的超大信息容量,越过具体的科学理论,直接面向各种不同问题的数据,确定参数的取值。这个专业方向叫做 AI for science,从业者大多是计算机科学家。
确定参数的方式,
首先要计算要交付的模型的函数值和因变量的不同,既然是计算,那就是一个新的函数,叫做损失函数 (loss function)。
然后让损失函数值最小化。这个最小化的过程也有一定之规,是一种运算,也就又是一个函数,有自己的参数。
最小化过程中的参数,完全由计算机科学家掌握,对理论和实验科学家屏蔽,这就是超参数。
回到动力学系统的相图
动力学系统本身是一组关于时间 t 的函数 (对不起这里也犯了一个符号两种含义的错误,但是不好改,约定俗成了)
这组函数由动力学微分方程确定
通过求解代数方程组
可以得到驻点关于动力学系统参数的函数
选择合适的驻点分量和感兴趣的参数 作图,得到的就是相图
还是洛伦兹系统,本系列第 4 篇没画图干讲了:
0 < r < 1 时,系统的驻点是原点,而且稳定;
r > 1 时,原点变为不稳定驻点,此时会出现两个新的稳定驻点: 和
时开始出现混沌。最常讨论的参数取值是 , , 此时 约为 24.76
如今可以把相图补上了:

本文收录于以下合集: