预测儿童身高案例

案例背景介绍

理论上,一个人的身高除了随年龄变大而增长之外,在一定程度上还受到遗传和饮食习惯以及其他因素的影响。在这里我们把问题简化一下,假定一个人的身高只受年龄、性别、父母身高、祖父母身高和外祖父母身高这几个因素的影响,并假定大致符合线性关系。

%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回归的效果好,比岭回归的效果差。
#当然我们可以调整参数,会得到不同结果。