目录
- 1、基础概念
- 2、一元线性回归
1、基础概念
- 机器学习(Machine Learning):通过学习算法从数据中学习模型的过程
例如从“房价y~面积x”的关系中学习:
建立模型:y=wx+b
学习模型:确定w,b(利用学习算法,找到统计规律
预测房价:使用模型计算房价
- 数据集(data set)/样本集(sample set):用来学习的数据的集合,例如鸢尾花数据集
样品:数据集中每一条记录称为“样本(sample)”:由属性(attribute)又叫(特征(feature))和标记/标签(label)组成(如房价,鸢尾花品种,相当于是要区分品种的特征)
- 监督学习(Supervised Learning):对有标记的数据集进行的学习,总结出数据之间的映射关系
监督学习可以分类为:
回归(regression):预测连续值,如:房价(就是“房价y~面积x”线性关系)
分类(classification):预测离散值, 如将鸢尾花分类,识别手写数字
- 模型【又叫:假设(hypothesis)/学习器(learner)】:估计函数
学习出来的模型应该尽可能逼近真实的存在的规律(叫:真相/真实(ground true)) - 无监督学习(Unsupervised Learning):样品数据没有标记时,挖掘数据内部蕴含的关系
聚类:把相似度高的样品聚合在一起,物以类聚,人以群分
距离:描述特征值之间的相似度
-
半监督学习(Semi-Supervised Learning):综合使用大量的没有标记数据和少量有标记的数据共同进行学习
-
人工智能:早期符号学习---->后来的机器学习 ,反映了从“理论研究、模型研究”到“应用研究(解决实际现实中的问题)”
因为很多模型都没法用符号来精确定义 -
一元线性回归:y=wx+b
回归:给定数据点拟合出最优的曲线
曲线为直线
模型变量:只有一个
模型参数:w权重,b偏置值
估计值、你和误差/残差:
-
损失函数/代价函数(Loss/cost function):模型的预测值与真实值的不一致程度
- 残差和最小:Loss=∑(yi-(w*xi+b))(i=1,2,3,…,n)(容易出现正负残差抵消的问题)
- 残差绝对值和最小:Loss=∑|yi-(w*xi+b)| (i=1,2,3,…,n)(不利于采用求导求Loss最小值)
- 残差平方和:Loss=0.5∑(yi-(wxi+b))² (i=1,2,3,…,n)(前面的0.5是为了方便求导运算)
又叫平方损失函数(Square Loss),与欧式距离一致- 均方误差(Mean Square Error):Loss=1/(2n)∑(yi-(wxi+b))² (i=1,2,3,…,n)
基于此公式的方法叫最小二乘法(Least Square Method)- 对残差平方和公式(平方损失函数)的w和b求偏导,即可求出w和b的取值,这种通过严格数学推导出来的解称为解析解(Analytical solution),也叫“封闭解/闭式解(Closed-form solution):
采用右式比较方便:
2、一元线性回归
实例
x=[137.97,104.50,100.00,124.32,79.20,99.00,124.00,114.00,
106.69,138.05,53.75,46.91,68.00,63.02,81.26,86.21]
y=[145.00,110.00,93.00,116.00,65.32,104.00,118.00,91.00,
62.00,133.00,51.00,45.00,78.50,69.65,75.69,95.30]
meanX=sum(x)/len(x) #x均值
meanY=sum(y)/len(y) #y均值
sumXY=0.
sumX=0.
for i in range(len(x)):
sumXY+=(x[i]-meanX)*(y[i]-meanY) #w的分子部分
sumX +=(x[i]-meanX)*(x[i]-meanX) #w的分母部分
w=sumXY/sumX #求斜率w
b=meanY-w*meanX #求截距b
print("w={},b={},\ntype=({},{})".format(w,b,type(w),type(b)))
#输出
w=0.8945605120044221,b=5.410840339418002,
type=(<class 'float'>,<class 'float'>)
- 预测房价
In [87]:
x_test=[128.15,45.00,141.43,106.27,99.00,53.84,85.36,70.00]
print("面积\t估计房价")
for i in range(len(x_test)):
print(x_test[i],"\t",round(w*x_test[i]+b,2)) #四舍五入,保留2位小数
#输出:
面积 估计房价
128.15 120.05
45.0 45.67
141.43 131.93
106.27 100.48
99.0 93.97
53.84 53.57
85.36 81.77
70.0 68.03
NumPy实现
import numpy as np
x=[137.97,104.50,100.00,124.32,79.20,99.00,124.00,114.00,
106.69,138.05,53.75,46.91,68.00,63.02,81.26,86.21]
y=[145.00,110.00,93.00,116.00,65.32,104.00,118.00,91.00,
62.00,133.00,51.00,45.00,78.50,69.65,75.69,95.30]
meanX=np.mean(x) #x均值
meanY=np.mean(y) #y均值
sumXY=np.sum((x-meanX)*(y-meanY)) #利用广播机制求:w的分子部分
sumX =np.sum((x-meanX)*(x-meanX)) #利用广播机制求:w的分母部分
w=sumXY/sumX #求斜率w
b=meanY-w*meanX #求截距b
print("w={},b={},\ntype=({},{})".format(w,b,type(w),type(b)))
- 预测房价
x_test=np.array([128.15,45.00,141.43,106.27,99.00,53.84,85.36,70.00])
y_pred=w*x_test+b #广播机制
print("面积\t估计房价")
for i in range(len(x_test)):
print(x_test[i],"\t",np.round(y_pred[i],2)) #np.round()四舍五入,保留2位小数
#输出:
面积 估计房价
128.15 120.05
45.0 45.67
141.43 131.93
106.27 100.48
99.0 93.97
53.84 53.57
85.36 81.77
70.0 68.03
TensorFlow实现
import tensorflow as tf
x=tf.constant([137.97,104.50,100.00,124.32,79.20,99.00,124.00,114.00,
106.69,138.05,53.75,46.91,68.00,63.02,81.26,86.21])
y=tf.constant([145.00,110.00,93.00,116.00,65.32,104.00,118.00,91.00,
62.00,133.00,51.00,45.00,78.50,69.65,75.69,95.30])
meanX=tf.reduce_mean(x) #x均值
meanY=tf.reduce_mean(y) #y均值
sumXY=tf.reduce_sum((x-meanX)*(y-meanY)) #利用广播机制求:w的分子部分
sumX =tf.reduce_sum((x-meanX)*(x-meanX)) #利用广播机制求:w的分母部分
w=sumXY/sumX #求斜率w,TensorFlow默认是32位浮点数,所以小数部分短一些
b=meanY-w*meanX #求截距b
print("权值w=",w.numpy(),"\n偏置值b=",b.numpy(),"\n线性模型:y=",w.numpy(),"*x+",b.numpy())
#print("权值w={0}\n偏置值b={1}\n线性模型:y={0}*x+{1}".format(w.numpy(),b.numpy()))
#输出:
权值w= 0.8945604
偏置值b= 5.4108505
线性模型:y= 0.8945604 *x+ 5.4108505
#若用下面那个已经注释掉的print,输出的小数位数会奇怪地变长:
权值w=0.8945603966712952
偏置值b=5.410850524902344
线性模型:y=0.8945603966712952*x+5.410850524902344
预测
In[10]:
x_test=tf.constant([128.15,45.00,141.43,106.27,99.00,53.84,85.36,70.00])
y_pred=w*x_test+b #广播机制
y_pred
Out[10]:
<tf.Tensor: shape=(8,), dtype=float32, numpy=
array([120.04876 , 45.66607 , 131.92853 , 100.475784, 93.97233 ,
53.573982, 81.77052 , 68.030075], dtype=float32)>
- 画图
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = "SimHei"
x=tf.constant([137.97,104.50,100.00,124.32,79.20,99.00,124.00,114.00,
106.69,138.05,53.75,46.91,68.00,63.02,81.26,86.21])
y=tf.constant([145.00,110.00,93.00,116.00,65.32,104.00,118.00,91.00,
62.00,133.00,51.00,45.00,78.50,69.65,75.69,95.30])
#计算模型
meanX=tf.reduce_mean(x) #x均值
meanY=tf.reduce_mean(y) #y均值
sumXY=tf.reduce_sum((x-meanX)*(y-meanY)) #利用广播机制求:w的分子部分
sumX =tf.reduce_sum((x-meanX)*(x-meanX)) #利用广播机制求:w的分母部分
w=sumXY/sumX #求斜率w,TensorFlow默认是32位浮点数,所以小数部分短一些
b=meanY-w*meanX #求截距b
print("权值w=",w.numpy(),"\n偏置值b=",b.numpy(),"\n线性模型:y=",w.numpy(),"*x+",b.numpy())
#print("权值w={0}\n偏置值b={1}\n线性模型:y={0}*x+{1}".format(w.numpy(),b.numpy()))#这样子输出的小数位数有古怪
#估计房价
x_test=np.array([128.15,45.00,141.43,106.27,99.00,53.84,85.36,70.00])
y_pred=(w*x_test+b).numpy() #广播机制
print("面积\t估计房价")
for i in range(len(x_test)):
print(x_test[i],"\t",round(y_pred[i],2))
#可视化
plt.figure()
plt.scatter(x, y, color="red",label="销售记录")
plt.scatter(x_test, y_pred, color="blue",label="预测房价")
plt.plot(x_test,y_pred,color="green",label="拟合曲线",linewidth=2)
plt.xlabel("面积(平方米)",fontsize=14)
plt.ylabel("价格(万元)",fontsize=14)
plt.suptitle("商品房销售价格评估",fontsize=20)
plt.legend(loc="upper left")
plt.show()
输出
权值w= 0.8945604
偏置值b= 5.4108505
线性模型:y= 0.8945604 *x+ 5.4108505
面积 估计房价
128.15 120.05
45.0 45.67
141.43 131.93
106.27 100.48
99.0 93.97
53.84 53.57
85.36 81.77
70.0 68.03
- 采用sklearn库的linear_model:
import numpy as np
from sklearn.linear_model import LinearRegression #线性回归
x=np.array([137.97,104.50,100.00,124.32,79.20,99.00,124.00,114.00,
106.69,138.05,53.75,46.91,68.00,63.02,81.26,86.21])
y=np.array([145.00,110.00,93.00,116.00,65.32,104.00,118.00,91.00,
62.00,133.00,51.00,45.00,78.50,69.65,75.69,95.30])
lr=LinearRegression() #创建一个线性回归模型
x_new=x.reshape(-1,1)
y_new=y.reshape(-1,1)
lr.fit(x_new,y_new) #训练出线性模型,需要x、y是二维数据
w=lr.coef_ #系数
b=lr.intercept_ #截距
print('w=',w,'\nb=',b)
#输出:
w= [[0.89456051]]
b= [5.41084034]