Python中的线性回归严重错误,回归线完全错误

时间:2018-12-31 08:18:35

标签: python scikit-learn linear-regression

大家好,我在kaggle(https://www.kaggle.com/sohier/calcofi,bottle.csv)的数据集中练习线性回归,我尝试通过以下方式实现它:

 ----drop table test 
    create table test (
    [Row ID] int ,
    BeginDate  date, 
    EndDate   date,
    [Unique ID]   varchar(15),
    Amount decimal(10,2)
    )
    insert into test values 
    (178484,'2018-01-01','2018-01-31','GroupID1',387.22),
    (176555,'2018-03-01','2018-03-31','GroupID1',751.07),
    (170120,'2018-04-01','2018-04-30','GroupID1',567.48),
    (172037,'2018-09-01','2018-09-30','GroupID1',587.51),
    (179024,'2018-10-01','2018-10-31','GroupID1',63.42),
    (182061,'2018-11-01','2018-11-30','GroupID1',728.04)

    select M as MonthNumber ,DATENAME(Month, DATEADD(Month, M, -1)) as  MonthName
    from (VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), (11), (12)) TT(M)
    where not exists (select * from test where TT.M=MONTH(BeginDate))
    /*
    MonthNumber MonthName
    ----------- ------------------------------
    2           February
    5           May
    6           June
    7           July
    8           August
    12          December
    */

当我查看截距和系数时会发生问题,

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

df = pd.read_csv("bottle.csv")
df

df1 = df.loc[:,"T_degC":"Salnty"]
df1 = df1.dropna()

from sklearn.cross_validation import train_test_split
from sklearn.linear_model import LinearRegression
X = df1["T_degC"]
y = df1["Salnty"]
X = X.values
type(X)
y = y.values
type(y)


X_train, X_test, y_train, y_test = train_test_split(X,y, test_size = 0.4)
lm = LinearRegression()

X_train = X_train.reshape(-1,1)
X_test = X_test.reshape(-1,1)
y_train = y_train.reshape(-1,1)

lm.fit(X_train, y_train)

分别为34.4和-0.05。但是,请考虑X和y变量的散点图:

lm.intercept_
lm.coef_

看起来负斜线绝对不可能成为该分布的回归线。因此,我想知道我做错了什么导致了这个结果。

1 个答案:

答案 0 :(得分:6)

这是一个非常有趣的案例研究!

回归线实际上是正确的,并且您的眼睛(和您的情节)在欺骗您

您生成的散点图如下所示:
Scatter plot with alpha=1

肯定看起来像是正斜率,对不对?对吧?
好吧,不。这里有很多要点,所以不可能看到最多的点。可能大多数情况下,大多数点都显示出向下的斜率,但它们都位于彼此的顶部,而其他极少数不在彼此之上的点则显示出向上的斜率。

更好的情节:降低视觉重叠

为了测试这一点,我绘制了不透明度低得多且标记大小较小的点(因此可以减少重叠量:

plt.scatter(X_train, y_train, alpha=0.002, s=1)
plt.show()

Scatter plot with less overlap
在这里,您可以看到实际上大多数点都呈向下的斜率(尽管也可能会认为线性相关不是建模相关的最佳方法)。请记住,线性回归试图拟合最佳的直线线,这意味着它遵循了大多数点,但是如果那里只有几个离群值,将无法捕获更困难的,不是直线的模式

事实上,线性相关系数也为负:

df1[["T_degC", "Salnty"]].corr()
#          T_degC    Salnty
#T_degC  1.000000 -0.505266
#Salnty -0.505266  1.000000

结论

简而言之:
 1.您的回归线似乎是正确的
 2.确保您正在查看正确的图-如果所有点都在彼此顶部,则散点图可能不是最佳选择。

编辑:视觉确认

另一幅图:散点图,其中包含您的回归: scatter plot with regression on top of it

(对于一条直线而言)这似乎是合理的,不是吗?

也许以任何方式用这么多点看另一幅图都更容易:

import seaborn as sns
sns.jointplot(x='T_degC', y='Salnty', data=df1, kind='hex')

hexbin jointplot

关节图通过为图形中许多点更强烈的部分着色来显式可视化重叠。这再次证实存在下降趋势,但是与该趋势相反的其他点也相对较少。 希望有帮助!