预测房价:回归问题——R语言9 g* N0 W4 E, U5 @* C
在回归问题中,我们的目标是预测连续值的输出,如价格或概率。将此与分类问题进行对比,分类的目标是预测离散标签(例如,图片包含苹果或橙色)。
& Z) A" X0 H$ \, A) g- T6 r5 T* e7 f( l9 N/ P3 {
问题描述
! {" ?( t* b7 D% G7 |0 w2 N我们将要预测20世纪70年代中期波士顿郊区房屋价格的中位数,已知当时郊区的一些数据点,比如犯罪率、当地房产税率等。
; j- F6 Y% i. Z; E0 Y# R本次用到的数据集包含的数据点相对较少,只有506个,分为404个训练样本和102个测试样本。输入数据的每个特征(比如犯罪率)都有不同的取值范围。例如,有些特征是比例,取值范围0 ~ 1;有的取值范围为1 ~ 12;还有的取值范围0 ~ 100,等等。
$ ?7 j5 c- i" v数据特征:4 J8 b& X% q ?. n3 }$ c! V, H
人均犯罪率。
5 S" x; S/ ^( }$ {4 c占地面积超过25,000平方英尺的住宅用地比例。
2 E9 v( E( |# j) V+ m每个城镇非零售业务的比例。0 h i" p4 n, X. s' U9 q, L
Charles River虚拟变量(如果管道限制河流则= 1;否则为0)。
2 u" ]0 q5 I, _( J$ e一氧化氮浓度(每千万份)。
6 p9 ^$ S& c8 d每栋住宅的平均房间数。: n$ X) V6 i) i* c. ^5 k; g' h
1940年以前建造的自住单位比例。
6 W6 g% S+ u8 Y* d _. O5 y6 W到波士顿五个就业中心的加权距离。$ |. f: o, Y- h. _* q- v* F( k
径向高速公路的可达性指数。
6 i/ a. P1 }9 | ?$ A' W, j每10,000美元的全额物业税率。
. h6 S1 V3 s* G' A, ^# C: c城镇的学生与教师比例。7 Y. a: o, H) c2 E6 O! b
1000 (Bk - 0.63)* 2其中Bk是城镇黑人的比例。
7 F2 t) v7 y1 f! }3 L9 u. Z人口比例较低的百分比。5 G8 {7 u$ W# [: m, d# a
1. 加载波士顿房价数据! R# b( u0 U7 ~4 E. O$ S; D5 ]
library(keras)
' n c4 p' s, O) H8 T$ ^9 @, Y$ x8 | N+ z' ~+ Z) \! n
boston_housing <- dataset_boston_housing()
4 R- Y: f0 u' S. q* E
% S6 D; E# y6 s0 ~$ } {8 }: s# ~) v5 vc(train_data, train_labels) %<-% boston_housing$train
% c6 {# W2 Q) [! N. @ [- A/ B# Yc(test_data, test_labels) %<-% boston_housing$test9 `! F! _- ^5 y, V+ @
" E; e4 m+ l5 u1 s1 N$ W5 j
每个样本有13个数值特征,目标是房屋价格的中位数,单位千美元。 2. 准备数据数据标准化 将取值范围差异很大的数据输入到神经网络中,这是有问题的。网络可能会自适应这种取值范围不同的数据,但学习肯定变得更加苦难。对于这种数据,普遍采用的最佳实践是对每个特征做标准化。
3 f3 ~. E7 J$ s/ ]# Test data is *not* used when calculating the mean and std.
P7 h3 D5 q5 `, }" `; a9 H
3 `: a+ T# m& o/ M9 A* x# Normalize training data
. ?- r2 H0 ^& x" ]* W$ F; G+ qtrain_data <- scale(train_data) 8 A& ?9 ]4 e3 M3 J& b# O2 s" G
3 D- X' X; F9 Y2 s8 U" _" r# Use means and standard deviations from training set to normalize test set4 A0 N6 ~% P0 W, T/ X J; w
col_means_train <- attr(train_data, "scaled:center")
( p- S% l8 f2 F, g1 z. ^col_stddevs_train <- attr(train_data, "scaled:scale")# N& j8 S# x, t5 h
test_data <- scale(test_data, center = col_means_train, scale = col_stddevs_train)0 F6 |/ q& O5 d* H* w/ N( j/ a
3 i: O' }. c8 v- Q3 s o# Q# f* f
3. 构建网络创建模型
3 g, i* r. p1 I) G& a0 K# _build_model <- function() {
; w/ q, M- Q# E a( l
( G- s" e* {& }3 F6 H model <- keras_model_sequential() %>%$ _/ e4 a- @ Q, ]- a' o
layer_dense(units = 64, activation = "relu",
4 h, L/ o( I1 n* F( `9 y, Z input_shape = dim(train_data)[2]) %>%$ A8 O# q1 f! U4 @2 r
layer_dense(units = 64, activation = "relu") %>%
2 ]7 O2 r. G' T- _% ~( G layer_dense(units = 1)
" ~# ^; B; W4 Q! t9 @
' p+ @8 S, ?6 O2 {: ~ model %>% compile(
& J4 m: f9 w- y/ ~! Z) W/ e loss = "mse",
9 H6 P# z+ B, a2 c9 T optimizer = optimizer_rmsprop(),' {" Q: i5 ?" a- e8 r+ I: C; {" Z* I8 I
metrics = list("mean_absolute_error")8 j6 H" r$ `' U- m
)4 x, U, {) f6 z+ }: t# v
' F) U1 P- V* } model
' @9 ]1 T; W& s4 C" M+ V( \# R# X}
8 f9 W% N* |: ^* u. J7 d4 b7 p! f' N" @3 m
model <- build_model()/ E( U" _% a$ j8 v0 H; _) \
model %>% summary(). W* G' O' X: b8 L
. a' ~, Z" `7 z/ o/ {# S
网络的最后一层只有一个单元,没有激活,是一个线性函数。这是标量回归(标量回归是预测单一连续值得回归)得典型设置。添加激活函数将会限制输出范围。 4. 训练模型+ l* o% z- D. L I7 q3 b' w
# Display training progress by printing a single dot for each completed epoch.+ g& g+ c. m( i8 x
print_dot_callback <- callback_lambda(! X% B& }; e7 O, q0 H+ p! \3 p+ b: a8 A
on_epoch_end = function(epoch, logs) {
% H0 ~" P4 ^6 x* \$ `& ~ if (epoch %% 80 == 0) cat("\n")
& l; S, @# W8 C( W2 y cat(".")4 Z1 f' M5 ]3 \8 w$ Q9 O
}
; l& [+ m, K6 U! L/ E2 i) : l* B8 k! O/ h: Z
7 t5 t8 h( Q2 Q6 X& j
epochs <- 500. r5 h6 O: P. _( z6 p' G8 y
* V4 m9 J9 [8 l* J
# Fit the model and store training stats {0 T1 q( o) N9 a% G+ w$ [+ g6 T9 o; v
history <- model %>% fit(4 U& I5 K) w( C. _
train_data,- Z9 d7 L( o# ^+ A+ V, g! d3 m
train_labels,
9 H$ o$ C* P& L6 `6 @8 I% @6 ^ epochs = epochs,: L. v2 e0 S+ M* V; P2 E) O
validation_split = 0.2,
1 Y* ^3 q, p. t J2 e0 k( ]1 P2 f verbose = 0,
& @4 H1 _' v: i8 x% w% N callbacks = list(print_dot_callback)9 A$ x) O$ c' \6 [
)# u. C# o0 O- E2 Y/ k
' X7 e' T9 a: F! [7 {, N" J
library(ggplot2)
, x" c, s! Y: Q) M E, f* N# z+ p1 O6 ]
plot(history, metrics = "mean_absolute_error", smooth = FALSE) +% {, b4 B( f5 ^7 t! c; o
coord_cartesian(ylim = c(0, 5))
0 U s6 r4 j8 T" H- B2 s9 b% d5 i! O0 e4 U+ `
![]()
6 |% o4 _( Z. F& Z4 k- s
: S2 e: v$ j: R/ X小结2 f' b: L. r: _5 _! e$ y
1)回归常用的损失函数是均方误差(MSE)。
1 Y' b3 T& \$ q; `2)常见的回归指标是平均绝对误差(MAE)。+ p; n0 l# m* L0 K
3)如果输入数据的特征具有不同的取值范围,应该先进行预处理,对每个特征单独进行缩放。) B/ @/ M# ^# j4 b$ r) ?
4)如果可用训练数据很少,最好使用隐藏层较少(通常只有1~2个)的小型网络,以避免严重的过拟合。
1 @7 x3 ?3 f2 M ~$ `/ u) U( |0 D3 q% h, q
& }% F* _, C; N, L7 @, t4 I+ G: G) j F& y( V
|