如何使用R语言手动实现机器学习KNN算法拟合——以得克萨斯州电力需求数据为例
Posted 爱尔兰粉公爵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用R语言手动实现机器学习KNN算法拟合——以得克萨斯州电力需求数据为例相关的知识,希望对你有一定的参考价值。
机器学习 (Machine Learning) 是目前备受追捧的学习领域之一,无论是学界还是业界都痴迷于机器学习的研究,甚至很多读BA的毕业生认为工作不用机器学习就会显得水平很低今天的学习记录就复习一下机器学习领域最最简单的一个算法——K-Nearest Neighbourhood Algorithm,中文名称应该是叫KNN算法。
今天的学习记录只是复盘一下我在春季学期数据挖掘课程中学到的KNN算法的入门案例,R本身可以使用FNN包自动运行KNN算法,但是今天我会手动计算拟合值。另外,进行数据分析时,一般按照80%/20%的比例将数据随机分成training data和test data,这里的演示没有做此区分。如果想细致深入了解KNN算法,推荐阅读USC教授Gareth James的An Introduction to Statistical Learning
入门案例是根据根据温度预测得克萨斯州用电量,数据"loadhou.csv"包含三个变量:时间 (Time)、用电量 (COAST)、温度 (KHOU)。
数据包含了2010-2016年度每天下午三点所测得的休斯顿机场温度以及得克萨斯州地区的用电总量。根据常识,当温度越低或者越高时,用电需求都会增大,所以二者的关系可视化之后应该呈现为开口向上的抛物线。如下图:
library(tidyverse)
library(gganimate)
loadhou <- read_csv("loadhou.csv")
ggplot(data = loadhou, mapping = aes(x = KHOU, y = COAST)) +
geom_point(color = "grey") +
theme_bw()
如果使用简单线性回归对曲线进行拟合,我们会得到一条直线,对结果的预测误差明显会很大。由于我们已知两者关系呈现抛物线状,所以我们可以在线性回归公式中添加独立变量的平方,获得更为精准的拟合曲线。
lm1 <- lm(COAST ~ KHOU, data = loadhou)
loadhou %>%
mutate(pred = lm1$fitted.values) %>%
ggplot(aes(x = KHOU, y = COAST)) +
geom_point(color = "grey") +
geom_line(aes(x = KHOU, y = pred),
color = "red", size = 1) +
theme_bw()
loadhou1 <- mutate(loadhou, KHOUSQ = KHOU * KHOU)
lm2 <- lm(COAST ~ KHOU + KHOUSQ, data = loadhou1)
loadhou1 %>%
mutate(pred = lm2$fitted.values) %>%
ggplot(aes(x = KHOU, y = COAST)) +
geom_point(color = "grey") +
geom_line(aes(x = KHOU, y = pred),
color = "red", size = 1) +
theme_bw()
虽然线性回归可以通过改变变量进而获得不同的拟合线,但是却并不能应付所有的情况,如果数据分布规律较为复杂,线性回归就不太适合用来进行拟合,太多的变量也会增加模型的复杂程度。这个时候,我们就可以采用KNN算法进行拟合。本案例中,KNN算法原理十分简单。在x轴随机选取一点x0,而后选取图中横轴距离x0最近的K个点,取他们的平均值作为x0对应的y0值,然后将所获得所有y0值连在一起即为我们的拟合曲线。我们以x0 = 20, K = 250为例:
x0_20 <- loadhou %>%
mutate(distance = abs(KHOU - 20)) %>%
arrange(distance) %>%
mutate(rank = row_number()) %>%
filter(rank <= 250)
ggplot(data = loadhou, aes(x = KHOU, y = COAST)) +
geom_point(color = "grey") +
geom_vline(xintercept = 20) +
geom_point(data = x0_20, aes(x = KHOU, y = COAST),
color = "blue") +
geom_point(data = x0_20, aes(x = 20, y = mean(COAST)),
color = "red", size = 2.5)
下面制作GIF动图进一步展示KNN算法原理,查看KHOU的取值范围,选取x0的值为-3到37,间隔为1,先筛选x0 = -3附近的250个点并生成表格knn,然后使用for语句计算剩余的点,并将所有表格合并为一个表格。
max(loadhou$KHOU)
min(loadhou$KHOU)
knn <- loadhou %>%
mutate(distance = abs(KHOU - (-3))) %>%
arrange(distance) %>%
mutate(rank = row_number(),
x0 = -3) %>%
filter(rank <= 250) %>%
mutate(mean = mean(COAST))
for (i in -2:37) {
knn1 <- loadhou %>%
mutate(distance = abs(KHOU - i)) %>%
arrange(distance) %>%
mutate(rank = row_number(),
x0 = i) %>%
filter(rank <= 250) %>%
mutate(mean = mean(COAST))
knn <- bind_rows(knn, knn1)
}
ggplot(data = loadhou, aes(x = KHOU, y = COAST)) +
geom_point(color = "grey") +
geom_vline(data = knn, aes(xintercept = x0))+
geom_point(data = knn, color = "blue")+
geom_point(data = knn, aes(x = x0, y = mean),
color = "red", size = 2.5)+
theme_bw()+
transition_states(x0) +
labs(title = "x0 = {closest_state}")
现在我们可以将拟合的值连接起来得到的我们的拟合曲线,在我演示的手动操作过程中,可以通过更改x0的取值间距或者K值得到不同的曲线。K值在KNN算法中最为重要,K值的选取也决定了模型的拟合度,一般我们会选取使得拟合值和实际值算术平方差最低的K值。在使用FNN包在自动运行KNN算法的时候,可以自行设定K值。
ggplot(data = loadhou, aes(x = KHOU, y = COAST)) +
geom_point(color = "grey") +
geom_line(data = knn, aes(x = x0, y = mean),
color = "red", size = 1) +
theme_bw()
上面演示的手动展示KNN算法的过程较为复杂,因为我想同时制作动图展现KNN算法实现的过程。下面演示一下比较直接的直接计算拟合值的做法:
x0 <- seq(-3, 36.5, 0.1)
y0 <- c()
for (i in x0) {
mean <- loadhou %>%
mutate(distance = abs(KHOU - i)) %>%
arrange(distance) %>%
mutate(rank = row_number()) %>%
filter(rank <= 250) %>%
summarise(mean = mean(COAST))
y0 <- append(y0, mean$mean)
}
pred <- data.frame(x0 = x0,
y0 = y0)
ggplot(data = loadhou, aes(x = KHOU, y = COAST)) +
geom_point(color = "grey") +
geom_line(data = pred, aes(x = x0, y = y0),
color = "red", size = 1) +
theme_bw()
今天的手算是我自己为了简单复习一下KNN算法的原理,实际使用可以直接用FNN包进行运算。
以上是关于如何使用R语言手动实现机器学习KNN算法拟合——以得克萨斯州电力需求数据为例的主要内容,如果未能解决你的问题,请参考以下文章
以❤️简单易懂❤️的语言带你搞懂有监督学习算法附Python代码详解机器学习系列之KNN篇
R语言plotly可视化:使用plotly可视化简单线性回归模型的回归线对比不同参数设置下的同一机器学习模型算法的拟合曲线三维回归曲面可视化实际值和回归预测值的散点图残差分析