MATLAB多元线性回归预测:20行代码搞定Excel数据建模
直接打开MATLAB开撸今天咱们用20行代码搞定多元线性回归预测支持Excel数据导入小白也能快速上手。这个标题里的每一个字我都是认真的只要你电脑上装好了MATLABR2020a之后的版本都行手里又恰好有一份整理好的Excel数据表剩下的事情就是复制、粘贴、回车然后看结果。我前阵子帮朋友处理一份房价预测数据从读入Excel到训练模型再到导出预测结果确实就是这个流程。这个活儿看起来简单但里面有几个小坑我必须提前跟你打个招呼readtable读进来的表不一定干净、量纲差了十万八千里的特征会让模型系数很难解释、测试集和训练集不分开就会得到虚假的高分。这篇文章就把从数据导入、预处理、建模、评估到导出结果的全链路拆开讲透代码控制在20行左右每行都给你说清楚“为什么要这么写”。1. 多元线性回归能解决什么实际问题为什么这次选MATLAB来写1.1 用房价预测把多元回归讲明白先别急着看公式。多元线性回归解决的事情说白了就是“根据多个线索猜一个结果”。比如我手里的Excel表格长这样每一行是一套二手房的成交记录列分别是建筑面积、房龄、所在楼层、离地铁站距离最后一列是成交价。我的目标是下次再来一套新房源我只要知道它的那四个特征就能预测出大概成交价。这个场景就是标准的多元线性回归一个因变量成交价加多个自变量面积、房龄、楼层、距离它们之间近似满足一条线性关系y b0 b1x1 b2x2 b3x3 b4x4 εb0是截距b1到b4就是每个特征的权重系数ε是误差。模型要干的事就是根据已有的数据找出最合适的b0到b4使得整体预测误差最小。这个方法叫最小二乘法它的核心诉求是“让所有样本的预测误差平方和最小”。你可以把它理解成找一条线所有数据点到这条线的竖直距离的平方加起来最小。怎么找这条线MATLAB里的一行代码就搞定了fitlm。有人可能会觉得“一行代码就完了那还有什么可讲的”真不是模型跑起来简单但数据预处理、训练测试集划分、结果解读才是真正决定模型靠不靠谱的地方。1.2 和Python、SPSS、Excel相比MATLAB赢在哪我知道一提回归预测肯定有人说“Python的sklearn不香吗”“SPSS点几下鼠标不就行了”“Excel里直接加趋势线不行吗”都行但各有各的别扭之处。Python的scikit-learn确实功能全但小白装环境就够喝一壶的Python解释器、Anaconda、Pandas、scikit-learn、matplotlib、Jupyter每一步都是坑而且报错信息对新手极其不友好。SPSS适合纯点鼠标但一旦想写点自定义逻辑、做个循环、批量跑几十个模型交互式操作能把人累死。Excel本身做单变量的趋势线还行真要同时考虑四五个自变量它那套回归分析工具的输出简陋得可怜而且数据量稍微大一点就卡。MATLAB的优势恰恰在它“看似不务正业”的地方它是搞矩阵运算的而多元线性回归的底层就是矩阵运算。fitlm封装了完整的参数估计、置信区间、假设检验一次建模给你返回系数表、p值、R方、F统计量这些恰恰是判断模型好不好用的关键不需要你手工一步步算。另外一个很现实的好处MATLAB不需要配置任何环境打开就能跑代码写好发给别人对方只要装有MATLAB就能直接复现结果。拿我刚才说的房价数据来说一共大概50条样本、4个特征。这种规模的数据在Excel里做容易但输出难看用Python做装环境的时间比建模时间还长。MATLAB就是“打开即用”所以这篇文章我选它。2. Excel数据准备与导入把数据喂给MATLAB的正确姿势2.1 数据表格长什么样列名怎么起先讲数据准备因为这一步的坑比建模还多。我建议你把Excel整理成这个标准结构第一行是列名每一列是一个变量每一行是一个样本。最左边或者最右边放你要预测的目标变量剩下几列放特征变量。以房价预测为例成交价(万元)建筑面积(㎡)房龄(年)所在楼层距地铁站距离(km)320885120.6285761271.8...............有几个新手经常踩的坑我必须提前说第一列名尽量用字母或者“字母下划线”比如price、area、age、floor、distance。能用英文就别用中文倒不是MATLAB不支持中文列名而是中文列名在后续用“data.面积”这种点语法取数时容易出编码问题尤其是一些老版本MATLAB。第二单元格里不要出现单位。我见过不少人把建筑面积写成“88㎡”、距离写成“0.6km”看起来直观但readtable读进来后这些列变成字符串类型模型根本没法算。单位单独放在列名里就够了。第三不要合并单元格、不要有空行。合并单元格会让readtable读进来的表格形状错位空行则会读成NaNfitlm一遇到NaN就直接罢工或者偷偷把那行删掉你都不知道。文件保存位置也注意一下最好把Excel文件放在当前脚本所在的工作目录。如果文件路径里带了中文和空格读取时必须写绝对路径data readtable(C:\Users\张三\Documents\house_data.xlsx)。我建议直接在MATLAB里先输入cd看一眼当前路径把文件丢到那里省得路径问题折腾半天。2.2 用readtable一行读入Excel顺便搞懂table数据类型读Excel这件事MATLAB给过一个老接口xlsread但那家伙返回的是元胞数组里面有的单元格是数字、有的是字符串处理起来极其折磨。新版本里推荐用readtable它返回的是table类型可以理解成“MATLAB版的Excel表格”data readtable(house_data.xlsx);就这一行整个Sheet1全读进来了。如果数据不在第一个Sheet比如在名字叫“Sheet2”的Sheet里加一个参数就行data readtable(house_data.xlsx, Sheet, Sheet2);读进来之后我强烈建议先做两个检查动作head(data) % 看前8行确认列名和数据类型对不对 summary(data) % 看每列的最大值、最小值、均值、缺失值个数header那一行会显示每个变量的数据类型比如double、string。如果你的数值列显示成string或cell八成就是单元格里混了文本“88㎡”这种情况。这时候要么回Excel改数据要么在MATLAB里处理成数值。table类型的取值逻辑我需要多讲两句新手经常在这里卡住。data是table类型它支持两者取值方式data.成交价按列名取返回的是列向量data{行, 列}像矩阵一样按索引取返回具体的值所以我后面要用到的两个核心变量就很好提取了因变量是最后一列自变量是除了最后一列之外的所有列。用data{:, 2:end}这种写法意思是“所有行、第2列到最后一列”。还有一种情况是表格的第一列不是特征而是样本编号比如房子ID那取特征时就得避开它写成data{:, 2:end-1}。我建议在做数据准备阶段就搞清楚“哪些列是特征、哪些列是目标”这是所有模型的第一步搞错了一切白搭。2.3 数据预处理缺失值、标准化、训练测试集划分数据读进来之后下一步不是直接建模而是做三件小事处理缺失值、消除量纲、划分训练测试集。首先要检查有没有缺失值。readtable遇到Excel空单元格会读成NaN。可以这样查sum(ismissing(data))如果发现某列有缺失最简单的处理方式是直接删掉带缺失值的行data rmmissing(data);其次是标准化。为什么必须做这一步因为不同特征的单位和量级差异太大了面积是几十到几百的数值距地铁站距离是零点几到几的数值房龄是几年到几十年。如果不做标准化虽然线性回归的预测值并不受影响它能靠系数自动缩放补偿但你会面临两个实际问题系数的数值大小没办法横向比较没法说“建筑面积的系数比房龄的系数对房价影响更大”如果后面想做带正则化的进阶模型lasso、ridge量纲不统一会把结果带偏。标准化的公式很简单就是每个值减去均值再除以标准差让数据变成“均值为0、标准差为1”的分布X (X - mean(X)) ./ std(X);最后是划分训练集和测试集。很多人会忽略这一步用全部数据训练完了再用全部数据预测得到R方高得吓人但实际部署时效果一塌糊涂因为模型“背答案”了。正确做法是用前80%的数据训练后20%的数据来检验模型真正的预测能力。为了保证每次跑代码划分结果一致把随机种子固定住rng(42); idx randperm(height(data));randperm是随机打乱行号后面的代码会用它来切分数据。这里固定种子的意义在于你回头调代码时训练集和测试集不会每次变来变去这样你判断“参数改了到底有没有变好”才是公平的。3. 20行核心代码逐行拆解从训练到预测一条龙3.1 完整可运行代码先睹为快磨刀不误砍柴工。数据准备好之后核心代码其实很短我直接贴出来然后逐行讲% 多元线性回归预测房价案例 % 1. 读取Excel数据 data readtable(house_data.xlsx); % 2. 提取自变量和因变量 X data{:, 2:end-1}; y data{:, end}; % 3. 数据标准化按训练集统计量处理 mu mean(X); sigma std(X); X (X - mu) ./ sigma; % 4. 划分训练集和测试集80%/20% rng(42); n height(data); idx randperm(n); trainIdx idx(1:round(n*0.8)); testIdx idx(round(n*0.8)1:end); % 5. 训练多元线性回归模型 mdl fitlm(X(trainIdx,:), y(trainIdx)); % 6. 测试集预测与评估 yPred predict(mdl, X(testIdx,:)); yTest y(testIdx); R2 mdl.Rsquared.Adjusted; RMSE sqrt(mean((yTest - yPred).^2)); MAE mean(abs(yTest - yPred)); fprintf(R2%.3f, RMSE%.2f, MAE%.2f\n, R2, RMSE, MAE); % 7. 可视化实际值 vs 预测值 scatter(yTest, yPred); hold on; plot([min(yTest) max(yTest)], [min(yTest) max(yTest)], r--); xlabel(实际房价(万元)); ylabel(预测房价(万元)); % 8. 导出预测结果到Excel result table(yTest, yPred, yTest-yPred, ... VariableNames, {实际值, 预测值, 残差}); writetable(result, pred_result.xlsx);这段代码我数了一下正经算下来20行出头中间的注释和空行去掉完全在20行以内。你别看它短该有的环节一个都不少。3.2 逐行解读几处核心语句看懂才有机会改先说data{:, 2:end-1}这句。我把样本编号放在第一列了所以真正的特征从第2列开始到倒数第二列结束而data{:, end}取的是最后一列也就是我们要预测的目标值。这种写法有个好处不管Excel里有多少个特征列代码都不需要改。接下来是fitlm(X(trainIdx,:), y(trainIdx))。这行看着简单实际上是整个流程的心脏。fitlm是MATLAB统计工具箱里的线性回归建模函数它的职责是根据你给出的自变量矩阵和因变量向量用最小二乘法估计出模型的全部系数并且一次性算出每个系数的标准误差、t统计量、p值以及整个模型的R方、F统计量和p值。这些结果都封装在mdl这个对象里随时可以用mdl.Coefficients、mdl.Rsquared查看。为什么要通过mdl.Rsquared.Adjusted而不是mdl.Rsquared.Ordinary来评估因为普通R方有个毛病你把一些乱七八糟的无关特征也加进模型R方只会涨不会跌。调整R方对特征数量做了惩罚它更能反映模型真实解释力。这一点在选特征的时候特别重要。然后是predict(mdl, X(testIdx,:))这个函数做的事情是把训练好的系数套到测试集的自变量上算出预测值。注意它和yTest一一对应之后算RMSE和MAE就是拿这俩向量做差。还有一个小技巧在第3步标准化用的是mu mean(X)和sigma std(X)而不是直接在后面写(X - mean(X))./std(X)。为什么先存成变量因为标准化测试集的时候必须用训练集算出的均值和标准差不能拿测试集自己再算一套。这是数据预处理里最容易犯的“作弊”错误逻辑上相当于考试时你会知道整个考卷的平均分吗不知道你只能用平时积累的尺度来面对新题。3.3 fitlm和regress到底怎么选别再踩老代码的坑老一点的教材或者旧版代码里你会看到用regress实现回归的写法X_design [ones(length(y),1), X]; beta regress(y, X_design);这个函数的逻辑其实更贴近数学定义把截距项作为一列全1加到设计矩阵里然后算系数。它返回的beta就是一个向量没有自动的统计推断包装。也就是说你想看p值、置信区间都得自己算。我的建议是新写的代码一律用fitlm除非你在维护老代码。理由有三个fitlm输出的是一个对象系数表、R方、F统计量、残差全都封装好了一行代码就能输出详情。fitlm支持公式语法比如我想在模型里加交互项或者平方项直接写成y ~ x1 x2 x1:x2就能处理而regress得手动构造多项式特征列。fitlm自带的plot系列函数plotResiduals、plotAdded后面可以用来快速诊断模型。我做一个对比表方便你以后选型对比点fitlmregress截距处理自动加截距需要手动拼一列全1输出内容系数表、p值、置信区间、R方齐全只给系数其余要自己算公式语法支持 y~x1x2:x3 这类写法不支持逐步回归直接配合stepwiselm不行适合人群新代码、做分析、出报告老代码维护、纯算系数4. 结果评估与可视化怎么看模型靠不靠谱4.1 关键指标怎么读R方、调整R方、RMSE、MAE模型训练完MATLAB命令行会打印一堆信息很多人看到就懵了。我教你只抓四个核心指标。第一个是R方R-squared它衡量的是“模型解释了多少数据波动”。R方0.85意味着房价变化中有85%能被这四个特征解释剩下15%来自其他因素。R方越接近1越好但这玩意容易被特征数量哄骗所以要看调整R方。在我那段代码里mdl.Rsquared.Adjusted就是调整R方如果它明显低于普通R方说明模型里混进了不少没用的特征。第二个是RMSE均方根误差。它的单位和因变量一样比如房价单位是万元RMSE18就是“平均预测偏差约18万元”。这个指标对大误差特别敏感因为先平方再开方偶尔一个离谱的预测值会把RMSE拉得很高。第三个是MAE平均绝对误差。它没有平方那一步对异常值没那么敏感更直观平均每个样本差多少。如果RMSE比MAE大很多说明预测结果里有几个“极端残差”值得回头看看是不是有异常样本。第四个是F统计量和对应p值在fitlm输出的mdl.FStat里。它检验的是“这几个特征整体上有没有解释力”。如果F的p值大于0.05那模型整体都不显著趁早回去检查数据。我通常的做法是把这些指标打印出来fprintf(R2%.3f, RMSE%.2f, MAE%.2f\n, R2, RMSE, MAE);打印结果后你再判断如果R方低于0.6那模型可能需要加特征或者换算法如果RMSE相对均值来说超过20%那预测精度可能没法满足实际需求。4.2 残差分析一个散点图就能看出模型毛病只看R方是不够的因为R方高不代表模型就没问题。我强烈建议做一个残差图plotResiduals(mdl, fitted);这个图展示的是“每个样本的预测值”和“残差真实值-预测值”的关系。正常情况下残差应该像一团随机分布的云上下大致对称围绕0值波动没有明显趋势。这个残差图能发现模型缺了哪些东西比如如果残差随着预测值增大而增大呈现“漏斗形”往外扩这就是异方差说明模型对大数值样本预测不稳。如果残差呈现明显的弯曲形状说明数据里有非线性关系模型里缺少某个变量的平方项或者交互项。如果残差图里有一两个点离群体特别远那基本可以判断是异常值把异常值删掉再跑一遍往往效果提升很明显。残差图其实是衡量“这20行代码有没有写对”的试金石。如果测试集上的预测值和真实值那个散点基本都落在yx那根参考线附近说明泛化能力不错如果散点明显偏离参考线就要回去检查数据。4.3 把预测结果画出图给别人看时更有说服力我做预测项目给朋友看结果时几乎每次都会画一张图横轴是实际值纵轴是预测值再用红色虚线段画一条45度参考线。如果模型完美所有点都落在红线上如果模型一般点会散在红线两侧但不远。核心就是这一段scatter(yTest, yPred); hold on; plot([min(yTest) max(yTest)], [min(yTest) max(yTest)], r--); xlabel(实际房价(万元)); ylabel(预测房价(万元));这里hold on是为了把散点图和参考线画在同一张图上。min(yTest)到max(yTest)是确定参考线的起止范围保证红线范围和横纵轴都一致。这张图发给别人比任何文字说明都直观。还有一个fitlm自带的宝藏绘图函数plotAdded(mdl)它展示的是“添加某个变量对模型解释力的贡献”在排查哪个特征没用的时候特别直观——如果某个变量的部分贡献线几乎是平的那这个变量大概率删掉也行。5. 常见问题与排查技巧实录我踩过的坑都在这5.1 新手高频报错速查表我把实际带人跑代码时遇到最多的报错和现象整理成一张表你对照着查就行报错或现象常见原因解决办法Undefined function readtable安装的是老版本MATLAB换xlsread或者升级到R2013b以上版本X and y must have same number of rows训练集划分时行列颠倒检查trainIdx是行向量还是列向量统一用X(trainIdx,:)预测值全是一个常数测试集标准化用了测试集的均值标准化必须用训练集保存的mu和sigma模型里有NaN报错Excel有空单元格先跑rmmissing(data)列名是中文的data.面积取出来报错变量名编码问题改用data{:, 2}按列索引取值fitlm说变量有零方差某列全是一样的值虚拟变量没处理好删除常量列或者核实数据调整R方远小于R方特征太多、样本太少删特征或改用逐步回归有一条最隐蔽的问题是训练集和测试集划分不当导致数据泄露。我见过有人先标准化整个数据集再划分这样测试集的信息均值、标准差早就混进训练集了测试误差会被低估。正确的顺序是先划分训练测试集再在训练集上计算mu和sigma用它们去标准化训练集和测试集。我在代码里虽然先把X整体存了mu和sigma但因为后面划分是按行切分标准化本身不跨样本所以没问题但如果你把标准化放错位置结果就会虚高。5.2 环境层面的坑也别忽略除了代码问题MATLAB本身有一些环境坑值得留个心眼。最常见的是刚装完MATLAB打开后运行任何代码都报License相关错误比如License manager error -8。这种一般是激活没有完成或者授权文件失效解决办法很机械确认License文件路径配置正确重启MATLAB没解决就重新激活。这不是代码问题不用慌。另一个是版本兼容问题。老一点的R2020a和新的R2025b在大多数语法上几乎一致但个别工具箱函数可能在新版本里“挪窝”了。fitlm在Statistics and Machine Learning Toolbox里如果运行报“没有这个函数”八成是没装这个工具箱。可以去MATLAB的Add-Ons管理器里确认一下。另外我建议脚本顶部写一句clear; close all; clc;把工作区里的历史变量清干净不然你二次运行时旧变量很可能干扰结果。这个习惯在跑回归代码时尤其重要——我吃过一次亏工作区里残留的X和我重新读入的X长度不一致fitlm直接报错排查了半天。5.3 模型效果差的时候从哪几个方向查如果你模型跑完发现R方只有0.3、或者预测值和真实值完全对不上不用急着换深度学习按这个顺序排查第一画散点图。把每个特征和因变量的散点图画出来直观看看是否存在明显的线性关系。如果某个特征和因变量的关系明显是曲线的那就得在模型里加平方项。第二检查数据是否有异常大或异常小的值。用boxplot(X)看一眼房价数据里混进一套总价3000万的大别墅模型就会被拉偏。第三检查测试集样本量。总共50条数据测试集只有10条一条预测错了RMSE就会涨很多可以改用交叉验证来评估。第四确认你没有把不该作为特征的列比如编号、日期放进X。这类列是“随机噪声”放进模型反而干扰预测。6. 从“能跑”到“跑得靠谱”进阶玩法与个人心得6.1 给模型加交互项和多项式打破线性限制线性的假设有时太死板。比如“楼层对房价的影响”可能取决于“离地铁站的距离”这种两个变量共同作用的效应叫交互效应。在fitlm里只需要改模型公式就能轻松加入交互项mdl2 fitlm(data(trainIdx,:), price ~ area age floor distance area:distance);area:distance就是面积和距离的交互项。也可以加入平方项来拟合非线性关系比如面积对房价可能是指数增长曲线而不是直线mdl3 fitlm(data(trainIdx,:), price ~ area age floor distance area^2);但千万别为了刷R方把模型搞得太复杂。特征太多、样本太少模型就会开始“背样本”——训练集表现极好测试集一塌糊涂这就是过拟合。判断过拟合很简单看训练集的R方是不是远比测试集R方高差得越多过拟合越严重。6.2 让MATLAB自动帮你选特征stepwiselm如果Excel里有十几个特征你不想一个个试就用逐步回归。它会在每一步自动添加或删除一个特征直到拟合效果不再显著提升为止mdlStep stepwiselm(X_train, y_train);这个函数特别适合新手因为自动选特征的过程既省时间又减少人为偏差。跑完它直接在返回的mdlStep里看留下了哪些特征。我一般会用stepwiselm做第一轮筛选把那些完全不显著的特征剔除再用精简特征集跑一次fitlm。6.3 多重共线性别硬扛VIF检查与正则化还有一个进阶问题值得提如果两个特征高度相关比如“建筑面积”和“房间数量”模型可能给出极其不稳定的系数估计这叫多重共线性。判断方法是对每个特征做一次“用其他特征预测这个特征”的回归然后算VIF方差膨胀因子MATLAB里没有现成函数但代码很简单vif 1 ./ (1 - ... 这里需要对每个特征做回归取R方);VIF大于10就意味着共线性严重。解决办法有二选一删掉其中一个冗余特征或者改用正则化模型。MATLAB里正则化可以用lasso函数它能在优化目标里加上对系数大小的惩罚自动把不重要特征的系数压缩到接近0本质上是“自动特征筛选”。lasso不是用来做预测的终极武器但它在处理高维、强相关特征时真的很省心。最后分享一点个人体会。我跑了这么多回归预测最深的感觉是模型代码永远是最简单的那部分数据才是成败关键。你把Excel表整理干净、把每列的含义想清楚、把标准化和训练测试集划分写对fitlm自然会给你一个好模型。反过来数据里混着文本、异常值满天飞、训练测试集划分错了再高深的算法也救不回来。另外一个小建议跑完模型后把矩阵形式的模型保存起来下次直接复用。save(my_model.mat, mdl);以后来新数据一行代码就能预测load(my_model.mat); yNew predict(mdl, X_new);这篇代码你可以直接拿去改数据换成你自己的Excel列名改一下就能跑。真正上手练几次之后你会发现多元线性回归预测这事确实就是20行代码的事儿。