这两天为了AU和访问量都在搞R,真是被逼迫的学啊...因为EXCEL太不智能了。还好之前上过JHU在coursera的统计分析一部分课程(后面听不下去逃掉了TAT),居然还用上了...
好吧,待我把这几天的工作总结一下。
有两组数值(以下script均用R写)
x<-c(22676277,20882843,20169758,19935222,19642157)
y<-c(128051,108686,99187,85127,81579)
要找出他们之间的关系,并且找出回归函数建模,以便当以后x值继续生产时,可以预测出y值。
首先先计算他们的相关性:
cor(x,y)
0.964
强正相关。可以考虑进行线性回归。
fit<-lm(y~x) ##lm()函数为线性回归函数
coef(fit) ##查看回归函数系数
(Intercept) x
-2.082360e+05 1.494401e-02
所谓线性回归就是 y=a+bx 求a,b的值。结果中,a值就是intercept截距值,b值为第二个x系数值。
我们来画个图
plot(x,y, xlab="x value", ylab="y value") #打出x,y实际关系的散点图
abline(fit) #添加线性回归线
当已知x值时,如何求y值呢? 用公式
y=a+bx=coef(fit)[1]+coef(fit)[2]*x
即可。
我们用实际数字验证一下:
x_test<-c(18589925,14656891)
y_test<-coef(fit)[1]+coef(fit)[2]*x_test
y_test为
但在实际观测中,当x下降到14656891时,y不可能是10798。说明我们这个模型在最后回归的时候斜率太大了,下降太快,不太符合实际。因此我们又建立了一个非线性回归,即用了指数回归模型来估计。
指数模型为y=a*x^b。代码如下:
x<-c(22676277,20882843,20169758,19935222,19642157)
y<-c(128051,108686,99187,85127,81579)
fit02<-nls(y~a*x^b, start=(list(a=1,b=1))) #nls()函数用来做非线性回归,里面参数第一个是模型等式,第二个start是估计参数初始值
运行时很快发现我们的代码报错 “singular gradient 奇艺梯度”。是因为start要求对系数的估计需要尽量贴近真实值,也就是说要尽量在一个数量级上。
但是不管你怎么改,就会发现这个回归特别难搞,各种报错,是因为需要回归的值都太大了。所以我找了个特别简单有效的方法——————就是降级,哈哈!把x和y从10e6下降到10e2,就会好算啦~比如在这个例子里:
x<-x/1000000
y<-y/10000
fit02<-nls(y~a*x^b, start=(list(a=1,b=1))) ##不会报错
plot(x,y) ##画散点图
lines(x,fitted(fit02)) ##添加回归曲线
辣么,如何已知x求y呢?
summary(fit02)
Formula: y ~ a * x^b
Parameters:
Estimate Std. Error t value Pr(>|t|)
a 0.001638 0.002441 0.671 0.55015
b 2.877748 0.489346 5.881 0.00981 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.638 on 3 degrees of freedom
Number of iterations to convergence: 25
Achieved convergence tolerance: 1.514e-06
这其中,系数a值就为参数中的a值0.001638,b值就为参数中的b值2.877748。求解如下:
> x_test<-c(18589925,14656891)
> x_test<-x_test/1000000 #x值降级
> y_test<-0.001638*x_test^2.877748 #套入公式
y_test
[1] 7.361649 3.714399
因为y被降过级,因此实际答案应为
y_test<-y_test*10000
y_test
[1] 73616.49 37143.99
数值相对符合实际。不过还要用真实值检验。当有更多的样本时,需要定时修正模型。