0x00 起因
看了吴恩达大佬的视频,有点似懂非懂的感觉,于是网上找了几篇实现的过程进行解析,加深理解。
这个是第一篇也是,房价的影响因素。
0x01 数据
数据来源:
来源prices.txt
房子面积,价格
1534,314900
1427,198999
1380,212000
1494,242500
1940,239999
2000,347000
1890,329999
4478,699900
1268,259900
2300,449900
1320,299900
1236,199900
2609,499998
3031,599000
1767,252900
1888,255000
1604,242900
1962,259900
3890,573900
1100,249900
1458,464500
2526,469000
2200,475000
2637,299900
1839,349900
1000,169900
2040,314900
3137,579900
1811,285900
1437,249900
1239,229900
2132,345000
4215,549000
2162,287000
1664,368500
2238,329900
2567,314000
1200,299000
852,179900
1852,299900
1203,239500
将以上数据保存文件为place.csv
保存在/home/lee/ml/1.hv/place.csv
0x02 思路
- 读取数据
- 将房子面积进行标准化
- 进行图形的散点显示
- 训练数据(训练3类,n=1,4,10阶拟合)
5.将散点和拟合曲线进行显示
0x03 训练数据
最重要的一步,单独分析。
- 我们训练的是
f(x|p;n)=p0x^n+p1x^n-1+...+pn
(p为系数,n为指数,m为样本数量) -
训练的方式:
使代价函数最下
L(p;n)=1/2 ∑(f(x|p;n)-y)^2
cost.png
0x04 人生苦短,我用python
numpy库
假设x=numpy.array([1,2,3,4,5,6,7,8,9])
1. array.mean()
求取平均值
>>> x.mean()
5.0
2. array.std()
求取标准差
>>> x.std()
2.581988897471611
3. numpy.polyfit(x,y,deg)
作用:训练函数
参数:
x:输入()
y:实际的输出
deg:多项式的阶数
返回:
p:使上述代价函数最小的参数p
4. numpy.polyval(p,x)
作用:将p和x带入多项式子计算结果
参数:
p:多项式的系数
x:输入的参数x
返回:
y:多项式的输出
>>> p=[1,2,3,4]
>>> numpy.polyval(p,2)
26
12^3+222+3*21+4=26
matplotlib.pythonplot库
图像显示的库,有点类似matlab的操作
import matplotlib.pyplot as plt
1. plt.figure()
创建窗口类
2. plt.scatter(x,y,s=20,c='b')
介绍:散点图,参数很多这个几个比较常用。
参数:
x:x轴坐标
y:y轴坐标
s:点的大小
c:颜色
>>> x=[1,2,3,4,5]
>>> y=[1,2,3,4,5]
>>> plt.scatter(x,y,s=20,c='r')
>>>plt.show()
3. plt.show()
将图形显示出来
4. plt.xlim(a,b)
x轴的范围
a:x轴左端
b:x轴右端
plt.ylim(a,b)同理
5. plt.legend()
显示使曲线对应的标签
6. plt.plot(x,y,label=)
画出(x,y)点构成的曲线
x:x轴坐标
y:y轴坐标
label:标签
>>> pi=3.14159
>>> x=[xx0.01 for xx in range(0,100)]
>>> y= [np.sin(xx2*pi) for xx in x]
>>> plt.plot(x,y,label="sin")
>>> plt.show()
0x05 具体代码
导入要用的库
import numpy as np
import matplotlib.pyplot as plt
数据导入
x,y=[],[]
# x为输入数据,y为目标数据
for sample in open("/home/lee/Desktop/ml/1.hv/place.csv",'r'):
area,value = sample.split(",")
x.append(float(area))
y.append(float(value))
x,y = np.array(x),np.array(y)
得到下面的内容
>>> x
array([2104., 1600., 2400., 1416., 3000., 1985., 1534., 1427., 1380.,
1494., 1940., 2000., 1890., 4478., 1268., 2300., 1320., 1236.,
2609., 3031., 1767., 1888., 1604., 1962., 3890., 1100., 1458.,
2526., 2200., 2637., 1839., 1000., 2040., 3137., 1811., 1437.,
1239., 2132., 4215., 2162., 1664., 2238., 2567., 1200., 852.,
1852., 1203.])
>>> y
array([399900., 329900., 369000., 232000., 539900., 299900., 314900.,
198999., 212000., 242500., 239999., 347000., 329999., 699900.,
259900., 449900., 299900., 199900., 499998., 599000., 252900.,
255000., 242900., 259900., 573900., 249900., 464500., 469000.,
475000., 299900., 349900., 169900., 314900., 579900., 285900.,
249900., 229900., 345000., 549000., 287000., 368500., 329900.,
314000., 299000., 179900., 299900., 239500.])
对x进行标准化
利用公式:x=(x-x.平均数)/x.方差
x=(x-x.mean())/x.std()
标准化后
>>> x
array([ 1.31415422e-01, -5.09640698e-01, 5.07908699e-01, -7.43677059e-01,
1.27107075e+00, -1.99450507e-02, -5.93588523e-01, -7.29685755e-01,
-7.89466782e-01, -6.44465993e-01, -7.71822042e-02, -8.65999486e-04,
-1.40779041e-01, 3.15099326e+00, -9.31923697e-01, 3.80715024e-01,
-8.65782986e-01, -9.72625673e-01, 7.73743478e-01, 1.31050078e+00,
-2.97227261e-01, -1.43322915e-01, -5.04552951e-01, -4.91995958e-02,
2.40309445e+00, -1.14560907e+00, -6.90255715e-01, 6.68172729e-01,
2.53521350e-01, 8.09357707e-01, -2.05647815e-01, -1.27280274e+00,
5.00114703e-02, 1.44532608e+00, -2.41262044e-01, -7.16966387e-01,
-9.68809863e-01, 1.67029651e-01, 2.81647389e+00, 2.05187753e-01,
-4.28236746e-01, 3.01854946e-01, 7.20322135e-01, -1.01841540e+00,
-1.46104938e+00, -1.89112638e-01, -1.01459959e+00])
将原始数据进行显示
plt.figure()
plt.scatter(x,y,c='g',s=6)
plt.show()
prices.png
训练
# 在(-2,4)区间上取100个点,等差
x0=np.linspace(-2,4,100)
# 设置3个阶数
test_set = (1,4,10)
for d in test_set:
p=np.polyfit(x,y,d)
cost=(0.5*((np.polyval(p,x)-y)**2).sum()) #计算代价函数
print(d,":",cost)
plt.plot(x0,np.polyval(p,x0),label="degree={}".format(d)) #描点
显示:
1 : 96732238800.35297
4 : 94112406641.67743
10 : 75874846680.09282
final.png
很明显
degree=10的时候,代价函数最小,但是图像可以看出defree=10已经过拟合了。
0x06 完整代码
import numpy as np
import matplotlib.pyplot as plt
##可视化输入数据
x,y=[],[]
for sample in open("/home/lee/Desktop/ml/1.hv/place.csv",'r'):
area,value = sample.split(",")
print(area,value)
x.append(float(area))
y.append(float(value))
x,y = np.array(x),np.array(y)
x=(x-x.mean())/x.std()
plt.figure()
plt.scatter(x,y,c='g',s=6)
plt.show()
## 取点训练
x0=np.linspace(-2,4,100)
## 多项式子的次数
# 模型预测函数
def get_model(deg):
return lambda input_x = x0:np.polyval(np.polyfit(x,y,deg),input_x)
#代价函数
def get_cost(deg,input_x,input_y):
return 0.5*((get_model(deg)(input_x)-input_y)**2).sum()
test_set = (1,4,10)
for d in test_set:
print(get_cost(d,x,y))
##96732238800.35292
#94112406641.67743
#75874846680.0928
plt.scatter(x,y,c='g',s=20)
for d in test_set:
plt.plot(x0,get_model(d)(),label="degree={}".format(d))
plt.xlim(-2,4)
plt.ylim(1e5,8e5)
plt.legend()
plt.show()
网友评论