机器学习(四):关于模型复杂度与模型性能的关系

  之前,我们分别使用线性模型以及二次模型对数据进行拟合,发现模型复杂度越高,越能贴合数据,预测精度越高。因此,我们是否可以认为只要算力条件充足,我们就可以尽可能地使用高复杂度模型进行函数的拟合?这就是本文讨论的主题:使用更复杂的模型会出现的问题以及解决方式。本文将分别使用线性模型、二次模型、五次模型以及七次模型分别进行房价数据的拟合,观察训练集和测试集的分布,以得到模型复杂度与模型性能的关系。https://www.iyakj.com/h-nd-15.html

  为了使现象更加明显,我们这次仅取少量的数据进行实验:10个数据组成的训练集和5个数据组成的测试集。关于这么做的原因,我们将在下一篇文章中进行解释。数据导入部分代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import random
# 导入数据
datasFile=pd.read_csv('data/data1810/data.txt',names=['size','price'])
datas=np.array(datasFile)
# 取前15个数据进行实验,并划分数据集,10个训练数据和5个测试数据
trainSet=datas[0:10,:]
testSet=datas[10:15,:]

trainX=trainSet[:,0]
trainY=trainSet[:,1]

testX=testSet[:,0]
testY=testSet[:,1]

# 归一化数据,最大最小值按照训练数据集来取
trainX_min_max=(trainX-np.min(trainX))/(np.max(trainX)-np.min(trainX));
trainY_min_max=(trainY-np.min(trainY))/(np.max(trainY)-np.min(trainY));

testX_min_max=(testX-np.min(testX))/(np.max(testX)-np.min(testX));
testY_min_max=(testY-np.min(testY))/(np.max(testY)-np.min(testY));

导入的数据分布如下: 训练集:测试集:

一、使用线性模型进行房价预测

  首先使用线性模型进行房价预测:

import random
# 初始化回归相关参数值
a=random.random()# 随机初始化一个值
b=random.random()

x=trainX_min_max
y=trainY_min_max

lr=0.1# 学习率
iter=500 # 训练次数
cost=0
# 开始训练
for i in range(1,iter+1):
    predict=a*x+b # 使用线性函数进行预测
    # 计算损失函数
    J=np.mean((predict-y)*(predict-y))
    cost=np.append(cost,J)
    # 计算损失函数的梯度值
    J_grad_a=np.mean((predict-y)*x)
    J_grad_b=np.mean(predict-y)
    # 进行参数迭代
    a=a-lr*J_grad_a
    b=b-lr*J_grad_b
    # 打印参数的值
    if i % 100 == 0:
        print("iter=%d," % i)
        print("cost=%.3f" % J)
        print("a=%.3f," % a)
        print("b=%.3f," % b)
        print("\n")

plt.plot(cost)

训练结果如下:最终训练集的误差为0.019 损失函数曲线:表明算法已经收敛 将结果可视化:使用训练好的模型进行测试:

# 进行预测
x=testX_min_max
y=testY_min_max
result=a*x+b
# 计算预测误差
err=np.mean((result-y)*(result-y))
# 打印误差
print('err=%.3f' % err)
# 绘制拟合结果
plt.scatter(x,y)
plt.scatter(testX_min_max,result)

测试结果如下:误差为0.028

二、使用二次模型进行预测

import random
# 初始化回归相关参数值
a=random.random()# 随机初始化一个值
b=random.random()
c=random.random()

x=trainX_min_max
y=trainY_min_max

lr=0.1# 学习率
iter=500 # 训练次数
cost=0
# 开始训练
for i in range(1,iter+1):
    predict=a*x*x+b*x+c # 使用二次函数进行预测
    # 计算损失函数
    J=np.mean((predict-y)*(predict-y))
    cost=np.append(cost,J)
    # 计算损失函数的梯度值
    J_grad_a=np.mean((predict-y)*x*x)
    J_grad_b=np.mean((predict-y)*x)
    J_grad_c=np.mean(predict-y)
    # 进行参数迭代
    a=a-lr*J_grad_a
    b=b-lr*J_grad_b
    c=c-lr*J_grad_c
    # 打印参数的值
    if i % 100 == 0:
        print("iter=%d," % i)
        print("cost=%.3f" % J)
        print("a=%.3f," % a)
        print("b=%.3f," % b)
        print("c=%.3f," % c)

        print("\n")

plt.plot(cost)

训练结果如下:可以看出,算法成功收敛,并且误差为0.016,效果优于线性模型,下面将模型运用到测试集上:

# 进行预测
x=testX_min_max
y=testY_min_max
result=a*x*x+b*x+c
# 计算预测误差
err=np.mean((result-y)*(result-y))
# 打印误差
print('err=%.3f' % err)
# 绘制拟合结果
plt.scatter(x,y)
plt.scatter(testX_min_max,result)

结果如下:测试集正确率为0.019,优于线性模型,符合我们之前的结论:模型越复杂,效果越好

三、使用五次方模型进行预测

训练部分代码:

import random
# 初始化回归相关参数值
a=random.random()# 随机初始化一个值
b=random.random()
c=random.random()
d=random.random()
e=random.random()
f=random.random()

x=trainX_min_max
y=trainY_min_max

lr=0.1# 学习率
iter=500 # 训练次数
cost=0
# 开始训练
for i in range(1,iter+1):
    predict=a*np.power(x,5)+b*np.power(x,4)+c*np.power(x,3)+d*np.power(x,2)+e*x+f # 使用五次函数预测
    # 计算损失函数
    J=np.mean((predict-y)*(predict-y))
    cost=np.append(cost,J)
    # 计算损失函数的梯度值
    J_grad_a=np.mean((predict-y)*np.power(x,5))
    J_grad_b=np.mean((predict-y)*np.power(x,4))
    J_grad_c=np.mean((predict-y)*np.power(x,3))
    J_grad_d=np.mean((predict-y)*np.power(x,2))
    J_grad_e=np.mean((predict-y)*x)
    J_grad_f=np.mean(predict-y)
    # 进行参数迭代
    a=a-lr*J_grad_a
    b=b-lr*J_grad_b
    c=c-lr*J_grad_c
    d=d-lr*J_grad_d
    e=e-lr*J_grad_e
    f=f-lr*J_grad_f
    # 打印参数的值
    if i % 100 == 0:
        print("iter=%d," % i)
        print("cost=%.3f" % J)
        print("a=%.3f," % a)
        print("b=%.3f," % b)
        print("c=%.3f," % c)
        print("d=%.3f," % d)
        print("e=%.3f," % e)
        print("f=%.3f," % f)

        print("\n")

plt.plot(cost)

训练结果:算法收敛,最终误差为0.015,优于二次模型,且预测更能贴合真实数据,下面来看测试集的效果:

# 进行预测
x=testX_min_max
y=testY_min_max
result=a*np.power(x,5)+b*np.power(x,4)+c*np.power(x,3)+d*np.power(x,2)+e*x+f
# 计算预测误差
err=np.mean((result-y)*(result-y))
# 打印误差
print('err=%.3f' % err)
# 绘制拟合结果
plt.scatter(x,y)
plt.scatter(testX_min_max,result)

结果如图:误差为0.023,测试集效果不如线性模型和二次模型。

四、七次模型进行预测

训练部分: 代码:

import random
# 初始化回归相关参数值
a=random.random()# 随机初始化一个值
b=random.random()
c=random.random()
d=random.random()
e=random.random()
f=random.random()
g=random.random()
h=random.random()

x=trainX_min_max
y=trainY_min_max

lr=0.1# 学习率
iter=2000 # 训练次数
cost=0
# 开始训练
for i in range(1,iter+1):
    predict=a*np.power(x,7)+b*np.power(x,6)+c*np.power(x,5)+d*np.power(x,4)+e*np.power(x,3)+f*np.power(x,2)+g*x+h # 使用七次函数预测
    # 计算损失函数
    J=np.mean((predict-y)*(predict-y))
    cost=np.append(cost,J)
    # 计算损失函数的梯度值
    J_grad_a=np.mean((predict-y)*np.power(x,7))
    J_grad_b=np.mean((predict-y)*np.power(x,6))
    J_grad_c=np.mean((predict-y)*np.power(x,5))
    J_grad_d=np.mean((predict-y)*np.power(x,4))
    J_grad_e=np.mean((predict-y)*np.power(x,3))
    J_grad_f=np.mean((predict-y)*np.power(x,2))
    J_grad_g=np.mean((predict-y)*x)
    J_grad_h=np.mean(predict-y)

    # 进行参数迭代
    a=a-lr*J_grad_a
    b=b-lr*J_grad_b
    c=c-lr*J_grad_c
    d=d-lr*J_grad_d
    e=e-lr*J_grad_e
    f=f-lr*J_grad_f
    g=g-lr*J_grad_g
    h=h-lr*J_grad_h
    # 打印参数的值
    if i % 1000 == 0:
        print("iter=%d," % i)
        print("cost=%.3f" % J)
        print("a=%.3f," % a)
        print("b=%.3f," % b)
        print("c=%.3f," % c)
        print("d=%.3f," % d)
        print("e=%.3f," % e)
        print("f=%.3f," % f)
        print("g=%.3f," % g)
        print("h=%.3f," % h)

        print("\n")

plt.plot(cost)

训练结果如下:算法收敛并且误差为0.012,优于上述所有模型。下面来看测试部分的结果: 代码:

# 进行预测
x=testX_min_max
y=testY_min_max
result=predict=a*np.power(x,7)+b*np.power(x,6)+c*np.power(x,5)+d*np.power(x,4)+e*np.power(x,3)+f*np.power(x,2)+g*x+h
# 计算预测误差
err=np.mean((result-y)*(result-y))
# 打印误差
print('err=%.3f' % err)
# 绘制拟合结果
plt.scatter(x,y)
plt.scatter(testX_min_max,result)

结果如下:误差竟然高达0.027,效果与线性模型接近

五、总结与分析

  经过上述实验,我们发现,模型越复杂,训练集的误差越低,说明拟合结果确实越来越贴合训练数据,这是合乎情理的。但是我们同时发现,模型越复杂,测试集的误差不一定越低,甚至有可能变大。因此,模型复杂度越高,模型的性能不一定越好。那么我们有没有办法克服这个现象呢?下一篇文章,我们将介绍上述现象产生的原因以及解决方法。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于机器学习与深度学习模型性能评估,我们可以从以下几个方面进行综合评估: 1. 准确率(Accuracy):衡量模型对于所有样本的分类/预测的正确率。 2. 精确率(Precision):衡量模型对真实类别为正类的样本,分类结果为正类的概率,即 TP / (TP + FP)。 3. 召回率(Recall):衡量模型对于真实类别为正类的样本,被分类为正类的概率,即 TP / (TP + FN)。 4. F1-Score:衡量模型精确率与召回率的平衡,其值为 2 * Precision * Recall / (Precision + Recall)。 5. ROC曲线(Receiver Operating Characteristic Curve):根据不同的样本阈值,绘制真正率(True Positive Rate)和假正率(False Positive Rate)之间的关系曲线。 6. AUC(Area Under Curve):ROC曲线下面积,该指标用来度量分类器的质量,其值在 0.5~1 之间,取值越接近 1,则分类器效果越好。 7. 交叉验证:在样本不充足时,可以采用交叉验证的方式对模型进行评估。交叉验证通常是将样本分为若干份,每份分别作为训练集和测试集,多进行训练和测试,最终得到平均表现。 8. 模型复杂度:可以通过模型参数数量、计算复杂度等方面来评估模型的复杂程度。应当避免使用复杂度很高的模型,在数据充足的情况下,应当优先选择简单模型,以避免过拟合和模型训练时间的过长。 通过综合以上这些方面的评估,选择最合适的模型

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值