预测儿童身高案例
案例背景介绍
理论上,一个人的身高除了随年龄变大而增长之外,在一定程度上还受到遗传和饮食习惯以及其他因素的影响。在这里我们把问题简化一下,假定一个人的身高只受年龄、性别、父母身高、祖父母身高和外祖父母身高这几个因素的影响,并假定大致符合线性关系。
%config InteractiveShell.ast_node_interactivity = 'all' #同时输出多行结果
import copy
import numpy as np
from sklearn import linear_model
# 训练数据,每一行表示一个样本,包含的信息分别为:
# 儿童年龄,性别(0女1男)
# 父亲、母亲、祖父、祖母、外祖父、外祖母的身高
x = np.array([[1, 0, 180, 165, 175, 165, 170, 165],
[3, 0, 180, 165, 175, 165, 173, 165],
[4, 0, 180, 165, 175, 165, 170, 165],
[6, 0, 180, 165, 175, 165, 170, 165],
[8, 1, 180, 165, 175, 167, 170, 165],
[10, 0, 180, 166, 175, 165, 170, 165],
[11, 0, 180, 165, 175, 165, 170, 165],
[12, 0, 180, 165, 175, 165, 170, 165],
[13, 1, 180, 165, 175, 165, 170, 165],
[14, 0, 180, 165, 175, 165, 170, 165],
[17, 0, 170, 165, 175, 165, 170, 165]])
# 儿童身高,单位:cm
y = np.array([60, 90, 100, 110, 130, 140, 150, 164, 160, 163, 168])
# 创建线性回归模型
lr = linear_model.LinearRegression()
# 根据已知数据拟合最佳直线
lr.fit(x, y)
LinearRegression(copy_X=True, fit_intercept=True, n_jobs=1, normalize=False)
# 待测的未知数据,其中每个分量的含义和训练数据相同
xs = np.array([[10, 0, 180, 165, 175, 165, 170, 165],
[17, 1, 173, 153, 175, 161, 170, 161],
[34, 0, 170, 165, 170, 165, 170, 165]])
for item in xs:
# 为不改变原始数据,进行深复制,并假设超过18岁以后就不再长高了
# 对于18岁以后的年龄,返回18岁时的身高
item1 = copy.deepcopy(item)
if item1[0] > 18:
item1[0] = 18
print(item, ':', lr.predict(item1.reshape(1,-1)))
[ 10 0 180 165 175 165 170 165] : [140.56153846]
[ 17 1 173 153 175 161 170 161] : [158.41]
[ 34 0 170 165 170 165 170 165] : [176.03076923]
岭回归、lasso回归、弹性网络回归预测结果比较
#以iris数据为例
#导入基本程序包
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
from sklearn import linear_model
from sklearn import metrics
#导入IRIS数据集
iris = load_iris()
#特征矩阵
X=iris.data
#目标向量
y=iris.target
from sklearn.cross_validation import train_test_split #导入数据划分包
#以20%的数据构建测试样本,剩余作为训练样本
X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.20,random_state =1)
elastic= linear_model.ElasticNet(alpha=0.1,l1_ratio=0.5) # 设置lambda值,l1_ratio值 ,这里需要注意的是,ElasticNet最基本的参数是alpha、l1_ratio,alpha其正则化选项中的λ,l1_ratio则是对应α。这里的random_state就是为了保证程序每次运行都分割一样的训练集和测试集。
elastic.fit(X_train,y_train) #使用训练数据进行参数求解
y_hat2 = elastic.predict(X_test) #对测试集的预测
print ("RMSE:", np.sqrt(metrics.mean_squared_error(y_test, y_hat2))) #计算RMSE
ElasticNet(alpha=0.1, copy_X=True, fit_intercept=True, l1_ratio=0.5,
max_iter=1000, normalize=False, positive=False, precompute=False,
random_state=None, selection='cyclic', tol=0.0001, warm_start=False)
RMSE: 0.25040264500501913
比较三种回归的不同
岭回归
ridge= linear_model.Ridge(alpha=0.1) # 设置lambda值
ridge.fit(X_train,y_train) #使用训练数据进行参数求解
y_hat = ridge.predict(X_test) #对测试集的预测
from sklearn import metrics #导入metrics评价模块
print ("RMSE:", np.sqrt(metrics.mean_squared_error(y_test, y_hat))) #计算RMSE
Ridge(alpha=0.1, copy_X=True, fit_intercept=True, max_iter=None,
normalize=False, random_state=None, solver='auto', tol=0.001)
RMSE: 0.24949141419802737
lasso回归
lasso= linear_model.Lasso(alpha=0.1) # 设置lambda值
lasso.fit(X_train,y_train) #使用训练数据进行参数求解
y_hat1 = lasso.predict(X_test) #对测试集的预测
print ("RMSE:", np.sqrt(metrics.mean_squared_error(y_test, y_hat1))) #计算RMSE
Lasso(alpha=0.1, copy_X=True, fit_intercept=True, max_iter=1000,
normalize=False, positive=False, precompute=False, random_state=None,
selection='cyclic', tol=0.0001, warm_start=False)
RMSE: 0.2555801316884705
#得到岭回归的RMSE: 0.249491414198027;得到Lasso回归的RMSE: 0.2555801316884705
#我们看到,在相同的lambda值下,ElasticNet回归的RMSE介于岭回归、lasso之间,即比Lasso回归的效果好,比岭回归的效果差。
#当然我们可以调整参数,会得到不同结果。