您的位置:首页 > 其它

小牛的学习笔记--波士顿房价数据回归分析

2020-07-16 05:54 211 查看

回归;标准化;加深;加宽;网格搜索优化参数

一、回归和分类

1.二分类问题输出层的激活函数是sigmode;多分类输出层的激活函数是softmax;回归问题输出层不需要激活函数
2.分类和回归本质是一样的,都是对输入做出预测,其区别在于输出的类型,分类归属到某一类;回归时预测出一个值
分类问题:输出的是离散型变量(+1,-1),是一种定性输出。(预测明天天气是阴、晴还是雨)。
回归问题:输出的是连续性变量,是一种定量输出。(预测明天的温度是多少度)。
3.分类模型和回归模型本质一样,分类模型是将回归模型的输出离散
4.比较常见的回归算法是线性回归算法(LR)。回归是对真实值的一种逼近预测。
最常见的分类方法是逻辑回归,或者逻辑分类。

二、步骤和数据初步分析

数据加载
建立回归模型
交叉验证
评估模型
本次所用到的数据集boston housing共包含506条数据,涵盖了波士顿不同郊区房屋14种特征的信息
这里有13个均为属性值(自变量):
CRIM: 城镇人均犯罪率
ZN: 住宅用地所占比例
INDUS: 城镇中非住宅用地所占比例
CHAS: CHAS 虚拟变量,用于回归分析
NOX: 环保指数
RM: 每栋住宅的房间数
AGE: 1940 年以前建成的自住单位的比例
DIS: 距离 5 个波士顿的就业中心的加权距离。
RAD: 距离高速公路的便利指数
TAX: 每一万美元的不动产税率
PRTATIO: 城镇中的教师学生比例
B: 城镇中的黑人比例
LSTAT: 地区中有多少房东属于低收入人群
目标变量(因变量)
MEDV: 自住房屋房价中位数(均值)
最后目标:
最后的均价和实际均价去比较观察逼近程度是多少

三、均方误差

这里用MSE(均方误差)评估模型的合理性:真实的值-预测的值,平方之和求和平均

线性回归的损失函数,在线性回归的时候我们的目的就是让这个损失函数最小当值为0时,说明预测值和真实值是一样的,均方误差越小说明预测性能越好

四、关于数据集

实际上,UCI机器学习存储库中数据集不是CSV格式,而是用空格分割属性,我们可以使用pandas库加载,然后,可以拆分输入(X)和输出(Y)属性,以便更容易使用Keras和scikit-learn进行建模。
之前讲过用逗号分隔的数据集,这里的数据集用空格分开属性,CSV格式文件可先用notepad++打开数据集看看用什么分割。

五、导包,加载数据集

回归:kerasregressor

import numpy
from pandas import read_csv
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasRegressor//回归模型
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import KFold
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline

分割属性值和标签值
Y存储的是真实的房价的均值;delim_whitespace=True//该数据是用空格隔开的,数据框把values取出来赋给X;

# load dataset
dataframe = read_csv("housing.csv", delim_whitespace=True, header=None)
dataset = dataframe.values
# split into input (X) and output (Y) variables
X = dataset[:,0:13]
Y = dataset[:,13]

六、定义模型和编译模型

我们可以适应Keras库提供的便捷包装对象来创建Keras模型并使用scikit-learn对其进行评估
Keras包装器需要一个函数作为参数,我们必须定义的函数负责创建要评估的神经网络模型
在下面,我们定义用于创建要评估的基准模型的函数,它是一个简单的模型,具有单个完全连接的隐藏层,其中隐藏层的神经元数量与输入属性相同(13)
没有激活层用于输出层,因为这是一个回归问题,我们对直接预测数值不进行转换
我们创建了一个实例,并将创建神经网络模型的函数名和一些参数传递给fit()函数,然后再传递给模型,例如epoch的数量和batch_size

# define base model
def baseline_model():
# create model
model = Sequential()
model.add(Dense(13, input_dim=13, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal'))//注意输出层不需要激活函数,这里是1个神经元,有n个就为n
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam')
return model

这里使用了有效的adam优化算法,并对均方误差损失函数进行了优化。这将与我们用来评估模型性能的度量相同。这里是损失函数是均方误差’mean_squared_error’,其中这里的优化函数跟分类问题一样。

# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)

七、评估模型

build_fn=baseline_model都要传那个创建模型的函数名传递参数 ,epochs=100表示迭代100次, batch_size=5表示批处理,每次处理多少个样本训练方式,verbose=0,0表示训练过程在输出窗口不显示

# evaluate model评估模型
estimator = KerasRegressor(build_fn=baseline_model, epochs=100, batch_size=5, verbose=0)
kfold = KFold(n_splits=10, random_state=seed)//交叉验证分的样本一样
results = cross_val_score(estimator, X, Y, cv=kfold)
print("Baseline: %.2f (%.2f) MSE" % (results.mean(), results.std()))//10交叉验证有10个结果,求平均值和方差

输出结果:

八、标准化评估模型

之前要注释掉评估模型的一堆代码
数据集的一个重要问题是输入属性的标度都不同,因为它们测量的数量不同,接着将数据进行规范化处理,并评估其效果。
在交叉评估的每一步,我们都可以使用scikit-learn的pipeline框架在模型评估过程中执行标准化。这样可以确保每个测试集的交叉验证数据不会泄漏到训练集中。

# evaluate model with standardized dataset标准化评估模型
estimators = []
estimators.append(('standardize', StandardScaler()))//标准化
estimators.append(('mlp', KerasRegressor(build_fn=baseline_model, epochs=50, batch_size=5, verbose=0)))//mlp多层感知机
pipeline = Pipeline(estimators)//封装到管道里,顺序进行
kfold = KFold(n_splits=10, random_state=seed)
results = cross_val_score(pipeline, X, Y, cv=kfold)
print("Standardized: %.2f (%.2f) MSE" % (results.mean(), results.std()))

结果输出:标准化之后性能明显变好

九、加深+标准化

注意注释掉定义模型和编译模型代码
额外再隐藏层加一个较小的隐藏层,性能应该有很好的提升

# define base model加深
def baseline_model():
# create model
model = Sequential()
model.add(Dense(13, input_dim=13, kernel_initializer='normal', activation='relu'))
model.add(Dense(6, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal'))
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam')
return model

结果输出:性能变好

十、加宽+标准化

增加第一层的特征数量,将基准模型的13个输入变量增加到20,迫使神经网络从输入数据中提取最重要的结构,结果稍微提升
注意注释掉定义模型和编译模型代码

# define wider model加宽
def baseline_model():
# create model
model = Sequential()
model.add(Dense(20, input_dim=13, kernel_initializer='normal', activation='relu'))
model.add(Dense(1, kernel_initializer='normal'))
# Compile model
model.compile(loss='mean_squared_error', optimizer='adam')
return model

结果输出:性能变好

十一、网格搜索优化参数

# MLP for Pima Indians Dataset with grid search via sklearn
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasClassifier//分类问题包装器
from sklearn.model_selection import GridSearchCV//用网格搜索做参数的最优化
import numpy

# Function to create model, required for KerasClassifier
def create_model(optimizer='rmsprop', init='glorot_uniform')://优化函数;初始化权重
# create model
model = Sequential()
model.add(Dense(12, input_dim=8, kernel_initializer=init, activation='relu'))
model.add(Dense(8, kernel_initializer=init, activation='relu'))
model.add(Dense(1, kernel_initializer=init, activation='sigmoid'))
# Compile model
model.compile(loss='binary_crossentropy', optimizer=optimizer, metrics=['accuracy'])//损失函数是二分类交叉熵
return model

# fix random seed for reproducibility
seed = 7//保证程序顺序运行
numpy.random.seed(seed)
# load pima indians dataset
dataset = numpy.loadtxt("pima-indians-diabetes.csv", delimiter=",")//,分隔
# split into input (X) and output (Y) variables
X = dataset[:,0:8]
Y = dataset[:,8]//定义输入变量和输出变量
# create model
model = KerasClassifier(build_fn=create_model, verbose=0)//传递创建函数的函数名build_fn=create_model
# grid search epochs, batch size and optimizer
optimizers = ['rmsprop', 'adam']
inits = ['glorot_uniform', 'normal', 'uniform']
epochs = [50, 100, 150]
batches = [5, 10, 20]//这两种参数2*3*3*3很多个参数任意组合,服务器承受不了,可以将epoch改小可是试试
param_grid = dict(optimizer=optimizers, epochs=epochs, batch_size=batches, init=inits)//循环尝试
grid = GridSearchCV(estimator=model, param_grid=param_grid)
grid_result = grid.fit(X, Y)
# summarize results网格搜索去打印里面的每个结果
print("Best: %f using %s" % (grid_result.best_score_, grid_result.best_params_))//打印出最好的成绩和最好的参数
means = grid_result.cv_results_['mean_test_score']//所有运行出来的准确值的平均值
stds = grid_result.cv_results_['std_test_score']//标准差
params = grid_result.cv_results_['params']//
for mean, stdev, param in zip(means, stds, params)://循环打印结果
print("%f (%f) with: %r" % (mean, stdev, param))

注:epochs = [50, 100, 150];batches = [5, 10, 20]多个参数任意组合,多种结果输出,网格搜索打印每个结果,最后打印出最好的分数和参数
服务器承受不住不运行了。。。。。。。。
我们可以单个优化,比组合优化简单比如改小epochs

十二、两个该例子的学习网址:

https://blog.csdn.net/NNNNNNNNNNNNY/article/details/52983386
https://www.jianshu.com/p/9d3c51cf32b8

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐