房价预测 线性回归 机器学习 :简单体验机器学习

该博客通过斯坦福大学机器学习课程中的房价预测数据集,介绍了如何使用线性回归进行数据预处理、模型训练及评估。在数据预处理阶段,对房屋面积进行了标准化。接着,利用多项式拟合训练模型,发现当多项式次数超过4时,模型开始出现过拟合现象,损失函数值增加。最后,通过可视化展示了不同次数的拟合结果,强调了度量模型泛化能力的重要性。
摘要由CSDN通过智能技术生成

采用的数据集出自斯坦福大学的机器学习课程
房价预测数据集链接

0.数据集以及问题背景

数据集中数据格式如下:每一行的前一项为房屋面积,后一项为房屋价格
2104,399900
1600,329900
2400,369000
1416,232000
3000,539900

请使用线性回归得到房屋价格预测模型,并且对模型做出评估。

1.编程实现

1_1.数据预处理

我们将输入数据x(面积area)标准化,数学公式如下:(std(x)为标准差)
在这里插入图片描述

#数据读取
def get_data():
    try:
        with open("D://1_Skills/MLearning/data/prices.txt") as f:
            for each_line in f.readlines():
                each_line=each_line.strip().split(',')
                area.append(float(each_line.pop(0)))        #别忘了把字符串数据转换成浮点数
                price.append(float(each_line.pop(0)))
    except IOError as ioerror:
        print('File Error'+str(ioerror))
        return(None)
    #1.数据预处理
    get_data()
    #转换成numpy数组
    area,price=np.array(area),np.array(price)
    #输入数据的标准化
    area=(area-area.mean())/area.std()

在这里插入图片描述
上图中横轴为标准化后的房屋面积,纵轴为房子价格。

1_2.训练模型

采用线性回归中的多项式拟合来训练模型
在这里插入图片描述

# deg参数代表模型中的多项式系数n,多项式次数
# 返回一个lamba表达式 可以根据输入的x,返回相对应的预测的y
def get_model(deg):
    # numpy.linspace()返回指定区间的均匀间隔的数字
    x = np.linspace(-2, 4, 100)
    return lambda input_area=x:np.polyval(np.polyfit(area,price,deg),input_area)

这里我们得到的模型,是一个lambda表达式,这里使用了numpy的两个函数,简单来讲,polyfit用于多项式拟合,它可以得到参数p,即多项式的各项系数,polyval函数则是根据多项式系数p和x求多项式的值y。
详细说明参见官方文档:numpy reference
在这里插入图片描述

1_3 模型评估

首先,我们计算一下不同次数的多项式拟合得到的模型 最终的损失函数 (即所谓的欧氏距离 前面1_2中有提到)

def get_cost(deg,input_area,input_price):
    return 0.5*((get_model(deg)(input_area)-input_price)**2).sum()
    #假设多项式次数分别为1-10 ,求对应的损失函数的值
    for deg in range(1,11):
        print("degree= "+str(deg)+' cost is ',end='')
        print(get_cost(deg,area,price))

结果如下:
D:\python\Anaconda3\python.exe D:/1_Skills/MLearning/房价预测/regression.py
degree= 1 cost is 96732238800.35297
degree= 2 cost is 96709317398.40862
degree= 3 cost is 94220569952.89433
degree= 4 cost is 94112406641.67743
degree= 5 cost is 83380464377.45618
degree= 6 cost is 79800924715.63896
degree= 7 cost is 79655422575.37532
degree= 8 cost is 79652499108.66656
degree= 9 cost is 77221612959.6537
degree= 10 cost is 75874846680.09285

接下来,我们可以使用Matplotlib库进行结果的可视化,这里我们绘制出不同次数的多项式进行拟合后的结果,观察是否出现了过拟合现象
在这里插入图片描述
上图所示,当拟合用多项式取10次时,就明显地出现了过拟合现象,通俗来讲就是周志华教授所说的:“当学习器把训练样本学得‘太好了’的时候,很可能已经把训练样本自身的一些特点当作了所有潜在样本都会具有的一般性质”,也就是说degree参数取10时,我们训练的模型泛化性能很差。

其实由前面求到的损失函数,我们也可以体会到,模型从degree=4开始,就开始出现过拟合现象了。

2.完整代码

import numpy as np
import matplotlib.pyplot as plt

#两个数组,分别存储面积和房价
area,price=[],[]

#数据读取
def get_data():
    try:
        with open("D://1_Skills/MLearning/data/prices.txt") as f:
            for each_line in f.readlines():
                each_line=each_line.strip().split(',')
                area.append(float(each_line.pop(0)))        #别忘了把字符串数据转换成浮点数
                price.append(float(each_line.pop(0)))
    except IOError as ioerror:
        print('File Error'+str(ioerror))
        return(None)

#2.模型训练
# deg参数代表模型中的多项式系数n,多项式次数
# 返回一个lamba表达式 可以根据输入的x,返回相对应的预测的y
def get_model(deg):
    # numpy.linspace()返回指定区间的均匀间隔的数字
    x = np.linspace(-2, 4, 100)
    return lambda input_area=x:np.polyval(np.polyfit(area,price,deg),input_area)

def get_cost(deg,input_area,input_price):
    return 0.5*((get_model(deg)(input_area)-input_price)**2).sum()

if __name__=='__main__':
    #1.数据预处理
    get_data()
    #转换成numpy数组
    area,price=np.array(area),np.array(price)
    #输入数据的标准化
    area=(area-area.mean())/area.std()

    #预处理后的数据 散点图 X轴:标准化area Y轴:房屋价格
    plt.figure()
    plt.scatter(area,price,c='g',s=12)
    plt.show()

    # numpy.linspace()返回指定区间的均匀间隔的数字
    x = np.linspace(-2, 4, 100)

    # 3.计算损失函数
    #假设多项式次数分别为1-10 ,求对应的损失函数的值
    for deg in range(1,11):
        print("degree= "+str(deg)+' cost is ',end='')
        print(get_cost(deg,area,price))

    #绘图观察是否出现了过拟合
    plt.scatter(area,price,c='r',s=20)
    #我们观察多项式次数分别为1 4 10时学习的结果
    for deg in (1,4,10):
        plt.plot(x,get_model(deg)(),label="degree = {}".format(deg))
    #限制X轴 Y轴的范围
    plt.xlim(-2,4)
    plt.ylim(1e5,8e5)
    #调用legend()使得曲线对应的label能正确显示
    plt.legend()
    plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值