关于数学建模的一些介绍
为了更好了解世界,我们可以通过数学来描述许多特定的现象,而数学模型就是现实世界的理想化,不过它永远不能完全精确地表示现实世界。
在这篇文章中,我将介绍一些数学建模的基本概念以及相应的基础知识,而关于更具体的如何建模的内容我将会在之后的文章中介绍。
一、动力系统
1.1 比例性
许多模型简化现实情况,其中一种非常强的简化关系就是比例性。具体地,我们说两个变量x与y是互成比例的,即一个变量总是另一个变量的整数倍,表达式如下:
我们可以将之记为:。
举个例子,我们知道胡克定律表达式就为y=kx,即弹簧的形变量y与受力x成正比,当弹簧受到k倍的x的力时,其将发生y的形变。如果我们具体对于力与形变量进行测量的话,我们通过将数据带入表达式就可计算出k的值,从而得到有关这个测量时所用的弹簧的一个数学模型。
1.2 关于变化的建模
对于变化的建模我们常用当前值减去变化量即可得到未来值,那么我们通过收集一段时间内的数据并画出图形,我们就可以识别出能够抓住这种变化趋势的模型的模式,如果是离散时间段的,则要使用差分方程,如果是连续的,则要使用微分方程。
1.3 差分
关于差分,我们可以有如下定义:
对于数列A={a0,a1,a2……}的一阶差分是:
那么我们就可以推导出第n个一阶差分为:
1.4 动力系统
如果我们将上述的差分的概念具体应用到关于随时间变化的事物上去建模,就可以得到动力系统,其具体概念如下:
动力系统(Dynamical System)是指随时间演化的一类系统,它可以用来描述自然界、工程技术、经济、社会等领域的各种过程。动力系统的理论研究的是系统状态随时间变化的规律,以及这些变化如何依赖于初始条件和系统参数。动力系统可以分为两大类:连续时间和离散时间动力系统。
此外,一个序列就是定义域为全体非负整数集合上的一个函数,其值域为实数的一个子集。一个动力系统就是序列各项之间的一种关系。数值解就是满足该动力系统的一张数值表。
1.5 猜测法
关于动力系统的解法中,有一种强有力的数学方法就是猜测法,即先假设动力系统解的形式,然后再去判断假设是否合理。举个例子:
考虑一个简单的一阶线性差分方程:
其中,是第n个时间步的状态,a与b是常数。
那么,我们可以先假设解的形式为:
则有:
将之带入原式并化简后即可得到:
此时,可将这个已获得的C带回原式,并且当n=0时,有:
最终,得到完整解为:
二、数学模型
2.1 系统
系统就是由一些有规律的相互作用或内在依赖关系联结在一起的对象的集合体。
2.2 数学模型
数学模型就是为了研究特定的实际系统或现象而设计的数学结构,图示、符号、模拟和实验结构都包括在内。
因此,数学模型具有以下的性质:
保真性:模拟现实世界的精确性;
成本:构建模型所需的总费用;
灵活性:当收集到足够的所需数据时,改变和控制影响该模型的诸多条件的能力。
2.3 建模过程
在建模时,通常要经过以下的步骤:
1.识别问题
2.做出假设,具体关于假设有这两方面:
a.变量分类
b.确定研究的所需的变量间的相互关系
3.求解模型
4.验证模型
5.实施模型
6.维修模型
2.4 模型的描述
我们通常用这三个词去描述一个模型,分别为:强健的、脆弱的、敏感的。其意思分别为:
强健的:如果一个模型的结论并不依赖于精确地满足其假设;
脆弱的:如果一个模型的结论依赖于要精确地满足某些类型的条件;
敏感的:模型的结论所依赖的某个条件变化时模型的变化程度,如果变化越大,则越敏感。
2.5 比例性建模
在刚才,我有简单介绍过比例性的概念,那么在这里我们进一步将比例性引入建模中去,利用比例性建模。具体可以举出以下例子:
2.6 几何相似性建模
首先,我们知道如果两个物体各点之间存在一个一一对应,使得对应点间举例之比对于所有的点间的都相同,那么则称为这个连个物体是几何相似的。比如常说的相似三角形。
那么利用这个性质去建模时,我们可以通过如下这个例子去理解:
在流体力学中,研究流体在管道、水坝、桥梁等结构中的流动特性时,常常使用缩尺模型来进行实验。假设要研究一个直径为 10 米的水坝的水流特性,选择比例为 1:10。
那么模型直径为:10米*1/10=1米
如果使用雷诺数作为相似准则,确保模型和实际系统的雷诺数相等:
假设实际系统的流速为 1 米/秒,密度为 1000 千克/立方米,黏度为 0.001 帕秒。
则带入求得:
(此时l作为特征长度,取10)
为了使模型的雷诺数相等,模型的流速 vm 应满足:
所以可得模型的流速vm的值为10m/s
三、模型拟合
3.1 误差与残差与偏差
首先,我们需要知道误差、残差、偏差这三者的概念:
误差:误差是指测量值或估计值与真实值之间的差异。
具体可以将之分为四类:公式化误差、截断误差、舍入误差与测量误差。
公式化误差一般源于一些变量可忽视的假设条件,或在各种子模型中描述变量间的关系的过分简化。
截断误差一般是因为求解一个数学问题所用数值方法导致的,比如用幂级数表示多项式近似sinx:
像这样的一个级数在使用时就会出现一个截断,而截尾后的多项式就会导致一个误差。
舍入误差是因为计算时使用有限小数位的机器引起的,比如1/3实际为0.3的3循环,但在实际表示时往往3是有限的,比如表示成这样:0.3333333333333,此时之后省去的3就成了一个误差。
测量误差是在数据收集时因为收集过程的不精确导致的,这无法避免。
而无论什么误差都可以用这个公式来表示:
误差=测量值-真实值
残差:残差是指在回归分析中,观测值与模型预测值之间的差异。
公式表示为:
残差=观测值-模型预测值
偏差:偏差是指模型的预测值与真实值之间的系统性差异。偏差可以反映模型的系统性误差,通常表现为模型在整体上高估或低估真实值。
一些数据点与直线间总存在一些纵向差异,我们称之为绝对偏差。
其公式可以表示为:
偏差=预测值-真实值
3.2 插值
在模型拟合过程中,插值是一种重要的技术,主要用于填补数据空白、平滑数据、以及在已知数据点之间进行预测。这些功能有助于提高模型的准确性和鲁棒性。
常见的插值方法有:
线性插值:通过连接相邻数据点的直线来估计中间点的值。适用于数据点较少且变化平缓的情况。
多项式插值:使用多项式函数来拟合已知数据点。常见的多项式插值方法包括拉格朗日插值和牛顿插值。
样条插值:使用分段多项式(样条函数)来拟合数据点,通常比多项式插值更平滑。常见的样条插值方法包括线性样条、二次样条和三次样条。
克里金插值:一种基于统计方法的插值技术,特别适用于空间数据的插值。考虑了数据点之间的空间相关性,生成的插值结果更加平滑和可靠。
3.3 变曲为直
在我们用图形进行拟合时,我们可能会遇到一些不方便绘图的曲线图,比如在如下的数据中:
x | 1 | 2 | 3 | 4 |
y | 8.1 | 22.1 | 60.1 | 165 |
此时,我们就需要变曲为直,而具体的方法也简单,就是对于y进行ln化,将之变形为lny,则原数据变为:
x | 1 | 2 | 3 | 4 |
y | 2.1 | 3.1 | 4.1 | 5.1 |
现在再要绘图就方便了。
3.4 曲线选择准则
关于如何选择曲线,我们有三个准则可以考虑,分别为切比雪夫准则、极小化绝对偏差、最小二乘准则。下面,我们来具体介绍下它们:
切比雪夫准则
切比雪夫准则也称为最大绝对误差最小化准则,目标是最小化所有数据点的最大绝对误差。具体来说,对于给定的数据点 (xi,yi)和模型预测值 y^i,切比雪夫准则的目标是:
其特点为:
关注最大误差:切比雪夫准则特别关注最大的单个误差,确保模型在最坏情况下的表现最优。
适用于对最大误差敏感的场景:例如,控制系统中,最大误差的控制往往比平均误差更重要。
极小化绝对偏差
极小化绝对偏差准则的目标是最小化所有数据点的绝对误差之和。具体来说,对于给定的数据点 (xi,yi) 和模型预测值 y^i,极小化绝对偏差准则的目标是:
特点:
关注总误差:极小化绝对偏差准则关注所有数据点的总误差,而不是单个数据点的误差。
对异常值不敏感:相比于最小二乘准则,极小化绝对偏差准则对异常值(outliers)不那么敏感,因为绝对误差不会像平方误差那样迅速增大。
最小二乘准则
最小二乘准则的目标是最小化所有数据点的平方误差之和。具体来说,对于给定的数据点 (xi,yi) 和模型预测值 y^i,最小二乘准则的目标是:
特点:
关注平方误差:最小二乘准则关注所有数据点的平方误差之和,使得较大的误差被放大。
数学性质良好:最小二乘准则有良好的数学性质,可以通过解析方法(如正规方程)或数值方法(如梯度下降)求解。
对异常值敏感:由于平方误差的放大效应,最小二乘准则对异常值非常敏感。
总结来说,切比雪夫准则是去找最大误差,以确保单个误差不过大,绝对偏差和是找所有偏差和,以求总体体上减少误差,同样的,最小二乘准则也是求总体上减小误差,但它是找所有偏差的平方和,而这个平方具有对于误差的放大作用,所以它比最小二乘法要敏感许多。
四、机器学习
数学建模中的机器学习是一种强大的工具,可以用于解决各种复杂的问题,从预测未来趋势到优化决策过程。机器学习通过从数据中自动学习模式和规律,构建模型来预测未知数据或解释现有数据。
4.1 基本概念
机器学习是一种人工智能技术,通过算法和统计模型,使计算机系统能够从数据中自动学习和改进,而无需显式编程。机器学习的目标是从数据中提取有用的信息,构建模型,以便对新数据进行预测或分类。
4.2 分类
关于机器学习可以将之分为监督学习、无监督学习、半监督学习以及强化学习。
4.3 常用算法
监督学习算法
线性回归:用于预测连续值的线性模型。
逻辑回归:用于分类任务的线性模型,输出概率值。
决策树:通过一系列规则对数据进行分割,构建树状模型。
随机森林:集成多个决策树,提高模型的稳定性和准确性。
支持向量机(SVM):通过找到最优超平面来分离不同类别的数据。
神经网络:模拟人脑神经元的工作方式,通过多层非线性变换来学习复杂的模式。
无监督学习算法
K均值聚类(K-means):将数据分成K个簇,每个簇内的数据点相似度较高。
层次聚类:通过逐步合并或分裂数据点来形成层次结构。
主成分分析(PCA):通过降维技术,保留数据的主要特征。
t-SNE:通过降维技术,将高维数据可视化为二维或三维数据。
强化学习算法
Q-learning:通过学习动作价值函数来选择最优动作。
深度Q网络(DQN):结合深度学习和Q-learning,处理高维状态空间。
具体关于这些算法的内容可以回看我之前的文章,其中几乎都有介绍。
4.4 步骤流程
在用机器学习取构建数学模型时,一般要经历以下步骤:
1.准备数据,在准备数据时,一般在收集到数据后,先要补充数据,将数据中的空白部分用相应的平均数或众数去填补,然后还需将数据中的异常值给去除。此外,还需要对于特征值进行选择,以提高模型的精确性;
2.选择模型,考虑最终要达到的目标去选择模型,比如要进行回归预测时就要选用线性回归模型、岭回归模型或lasso回归模型等,而如果是要进行分类则可以考虑SVM或逻辑回归等模型;
3.训练模型,在训练模型前,先要划分数据,将原本的数据划分为训练数据与测试数据,有时还需要再划分出验证数据来,而对于训练数据与测试数据的划分一般划分的比例为7:3或8:2,然后将训练数据带入到模型中,让机器根据这些数据来自行构建数学模型;
4.模型评估,当我们训练好模型后,就需要对于模型进行评估,一般考虑的性能指标可以均方误差(MSE)、准确率、召回率、F1分数等,此外,还可以使用交叉验证技术评估模型的稳定性和泛化能力;
5.模型改进,在使用训练数据集训练模型后,还需通过优化算法(如梯度下降)最小化损失函数;
6.模型应用,将训练好并优化好后的模型对新来的数据进行预测;
7.模型维护,我们需要定期对于模型的性能进行测量,以确保模型对于新数据的预测依然有效。并且,随着新数据的积累,重新训练模型以保持其性能。
在这里,我可以给出一个简单的用机器学习进行数学建模的python代码:
import numpy as np
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, classification_report
from sklearn.feature_selection import SelectKBest, f_classif
from scipy import stats
import matplotlib.pyplot as plt
# 1. 准备数据
# 1.1 数据收集
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['target'] = iris.target
# 1.2 数据填补
# 假设数据集中存在缺失值,用平均数填补
df.fillna(df.mean(), inplace=True)
# 1.3 去除异常值
# 使用Z-score方法去除异常值
z_scores = np.abs(stats.zscore(df.drop(columns=['target'])))
df_no_outliers = df[(z_scores < 3).all(axis=1)]
# 1.4 特征选择
# 使用SelectKBest选择最重要的特征
selector = SelectKBest(score_func=f_classif, k=3)
X_selected = selector.fit_transform(df_no_outliers.drop(columns=['target']), df_no_outliers['target'])
# 分离特征和目标变量
X = X_selected
y = df_no_outliers['target']
# 2. 选择模型
# 选择几种不同的分类模型
models = {
'Logistic Regression': LogisticRegression(),
'Support Vector Machine': SVC(),
'Random Forest': RandomForestClassifier()
}
# 3. 训练模型
# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 标准化特征
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
# 训练模型
for name, model in models.items():
model.fit(X_train_scaled, y_train)
# 4. 模型评估
# 评估模型
results = {}
for name, model in models.items():
y_pred = model.predict(X_test_scaled)
results[name] = {
'Accuracy': accuracy_score(y_test, y_pred),
'Precision': precision_score(y_test, y_pred, average='macro'),
'Recall': recall_score(y_test, y_pred, average='macro'),
'F1 Score': f1_score(y_test, y_pred, average='macro')
}
print(f'{name}:')
print(classification_report(y_test, y_pred))
# 5. 模型改进
# 使用GridSearchCV进行超参数调优
param_grid_lr = {'C': [0.1, 1, 10, 100], 'penalty': ['l1', 'l2']}
param_grid_svm = {'C': [0.1, 1, 10, 100], 'kernel': ['linear', 'rbf']}
param_grid_rf = {'n_estimators': [10, 50, 100, 200], 'max_depth': [None, 10, 20, 30]}
grid_search_lr = GridSearchCV(LogisticRegression(), param_grid_lr, cv=5, scoring='accuracy')
grid_search_svm = GridSearchCV(SVC(), param_grid_svm, cv=5, scoring='accuracy')
grid_search_rf = GridSearchCV(RandomForestClassifier(), param_grid_rf, cv=5, scoring='accuracy')
grid_search_lr.fit(X_train_scaled, y_train)
grid_search_svm.fit(X_train_scaled, y_train)
grid_search_rf.fit(X_train_scaled, y_train)
best_models = {
'Logistic Regression': grid_search_lr.best_estimator_,
'Support Vector Machine': grid_search_svm.best_estimator_,
'Random Forest': grid_search_rf.best_estimator_
}
# 6. 模型应用
# 使用最佳模型进行预测
for name, model in best_models.items():
y_pred = model.predict(X_test_scaled)
print(f'{name} (Best Model):')
print(classification_report(y_test, y_pred))
# 7. 模型维护
# 假设有新的数据
new_data = np.array([[5.1, 3.5, 1.4], [6.2, 2.9, 4.3]]) # 新数据
new_data_scaled = scaler.transform(new_data)
# 使用最佳模型对新数据进行预测
for name, model in best_models.items():
predictions = model.predict(new_data_scaled)
print(f'{name} Predictions: {predictions}')
# 定期评估模型性能
# 假设有新的测试数据
new_X_test, new_y_test = X_test[:10], y_test[:10] # 新的测试数据
new_X_test_scaled = scaler.transform(new_X_test)
for name, model in best_models.items():
new_y_pred = model.predict(new_X_test_scaled)
new_accuracy = accuracy_score(new_y_test, new_y_pred)
print(f'{name} New Accuracy: {new_accuracy}')
# 重新训练模型
all_X = np.concatenate([X_train, new_X_test])
all_y = np.concatenate([y_train, new_y_test])
all_X_scaled = scaler.fit_transform(all_X)
for name, model in best_models.items():
model.fit(all_X_scaled, all_y)
y_pred = model.predict(X_test_scaled)
print(f'{name} (Re-trained):')
print(classification_report(y_test, y_pred))
此上