[二]机器学习之回归

2.1 线性回归

2.1.1 实验数据

    1.数据描述

数据来自出版书籍《An Introduction to Statistical Learning with Applications in R》(Springer,2013),作者Gareth James,Daniela Witten,Trevor Hastie and Robert Tibshirani。共200条数据,每条数据4个属性。

数据下载地址:http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv

    2.数据集信息

数据共4列200行,每一行为一个特定的商品,前3列为输入特征,最后一列为输出特征。

输入特征:

TV:该商品用于电视上的广告费用(千元,下同)

Radio:在广播媒体上投资的广告费用

Newspaper:用于报纸媒体的广告费用

输出特征:

Sale:该商品的销量

    3.数据样例

2.1.2 实验过程

运行python

    1.收集、准备数据

import pandas as pd
data = pd.read_csv("Advertising.csv")
data.head()#显示前5行

查看数据集大小

data.shape

    2.分析数据

import matplotlib.pyplot as plt
import pandas as pd
if __name__ == "__main__":
    path = "Advertising.csv"
#pandas读入数据
    data = pd.read_csv(path)
    x = data[['TV','radio','newspaper']]
    y = data['sales']
    plt.figure(figsize=(9,12))
    plt.subplot(311)
    plt.plot(data['TV'],y,'ro')
    plt.title('TV')
    plt.grid()
    plt.subplot(312)
    plt.plot(data['radio'],y,'g^')
    plt.title('radio')
    plt.grid()
    plt.subplot(313)
    plt.plot(data['newspaper'],y,'b*')
    plt.title('newspaper')
    plt.grid()
    plt.tight_layout()
    plt.show()
    

得到绘图:

    3.使用pandas构建特征向量x和列标签y

feature_cols = ['TV','radio','newspaper']
X = data[feature_cols]
print X.head()
print type(X)
print X.shape
y = data['sales']
print y.head()

结果如下:

    4.构建训练集与测试集

from sklearn.cross_validation import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=1)
#默认75%为训练集,25%为测试集
print X_train.shape
print y_train.shape
print X_test.shape
print y_test.shape

    5.sklearn线性回归

from sklearn.linear_model import LinearRegression
linreg = LinearRegression()
model = linreg.fit(X_train,y_train)
print model
print linreg.intercept_
print linreg.coef_
zip(feature_cols,linreg.coef_)

由此,可以得到各项系数:y=2.8769+0.0465*TV+0.1791*radio+0.00345*newspaper

    6.预测

y_pred = linreg.predict(X_test)
print y_pred
print type(y_pred)

    7.回归问题的评价测度

对于分类问题,评价测度(evalution metrics)是准确率,但这种方法不适用与回归问题。我们使用连续数值的评价测度

(1)平均绝对误差(Mean Absolute Error,MAE)

(2)均方误差(Mean Squared Error,MSE)

(3)均方根误差(Root Mean Squared Error,RMSE)

此处使用RMSE:

print type(y_pred),type(y_test)
print len(y_pred),len(y_test)
print y_pred.shape,y_test.shape
from sklearn import metrics
import numpy as np
sum_mean=0
for i in range(len(y_pred)):
    sum_mean += (y_pred[i]-y_test.values[i])**2

print "RMSE by hand:",np.sqrt(sum_mean/len(y_pred))

    8.作图

import matplotlib.pyplot as plt
plt.figure()
plt.plot(range(len(y_pred)),y_pred,'b',label="predict")#蓝色线表示预测值
plt.plot(range(len(y_pred)),y_test,'r',label="test")#红色线为真实值
plt.legend(loc="upper right")#右上角显示标签
plt.xlabel("the number of sales")
plt.ylabel("value of sales")
plt.show()

2.1.3 结果分析

根据结果y=2.8769+0.0465*TV+0.1791*radio+0.00345*newspaper可以看出,newspaper的系数很小,再观察收益-newspaper散点图,我们发现newspaper的线性关系不明显,因此我们可以尝试去除这个特征,看看回归预测的结果如何。

feature_cols = ['TV','radio']
X = data[feature_cols]
from sklearn.cross_validation import train_test_split
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=1)
from sklearn.linear_model import LinearRegression
linreg = LinearRegression()
model = linreg.fit(X_train,y_train)
zip(feature_cols,linreg.coef_)
y_pred = linreg.predict(X_test)
sum_mean=0
for i in range(len(y_pred)):
    sum_mean += (y_pred[i]-y_test.values[i])**2

print "RMSE by hand:",np.sqrt(sum_mean/len(y_pred))
plt.figure()
plt.plot(range(len(y_pred)),y_pred,'b',label="predict")#蓝色线表示预测值
plt.plot(range(len(y_pred)),y_test,'r',label="test")#红色线为真实值
plt.legend(loc="upper right")#右上角显示标签
plt.xlabel("the number of sales")
plt.ylabel("value of sales")
plt.show()

测得结果为:1.387

预测值与真实值的关联图如下:

在移除newspaper特征之后,得到的RMSE值变小了,说明newspaper特征可能不适合作为预测销量的特征,因此,我们得到了新的模型。

2.1.4 注意事项

本模型虽然简单,但它涵盖了机器学习的相当部分内容,如使用75%的训练集和25%的测试集,这往往是探索机器学习的第一步。得到的线性模型发现有负权,我们使用最为简单的方法:直接删除;但这样做,仍然得到了更好的预测结果。

在机器学习中,由“奥卡姆剃刀”原理:如果能够用简单模型解决问题,则不用复杂的模型,因为复杂模型往往增加了不确定性,造成过多的成本浪费,且容易过拟合。

2.2 Logistic回归

2.2.1实验数据

鸢尾花数据集或许是最有名的模式识别测试数据。该数据集包括3个鸢尾花类别,每个类别50个样本,其中一个类别是与另外两类线性可分的,而另外两类线性不可分。

由于最原始的数据集存在两个错误(35号和38号样本),因此我们在试验中使用的是修正过的数据。

数据下载地址:http://archive.ics.uci.edu/ml/dataset/Iris

2.2.2实验过程

(一)数据描述

该数据集共包含150行,每行1个样本,每个样本有5个字段:花萼长度(cm),花萼宽度(cm),花瓣长度(cm),花瓣宽度(cm),类别(三种,Iris Setosa,Iris Versicolor,Iris Virginica)

数据集特征 多变量 记录数 150
属性特征 实数 属性数目 4
相关应用 分类 缺失值

(二)实验代码

import numpy as np
from sklearn.linear_model import LogisticRegression
import matplotlib.pyplot as plt

def iris_type(s):
    it = {'Iris-setosa':0,'Iris-versicolor':1,'Iris-virginica':2}
    return it[s]

if __name__ == "__main__":
    path = 'iris.data'#数据文件路径
    #路径,浮点型数据,逗号分隔,第4列用函数iris_type单独处理
    data = np.loadtxt(path,dtype=float,delimiter=',',converters={4:iris_type})
    #将数据的0-3列组成x,第4列得到y
    x,y = np.split(data,(4,),axis=1)
    #为了可视化,仅使用前两列特征
    x = x[:,:2]
    #Logistic回归模型
    logreg = LogisticRegression()
    #根据数据[x,y],计算回归参数
    logreg.fit(x,y.ravel())
    #画图
    #横纵各采样多少个值
    N,M = 500,500
    #得到第0列范围
    x1_min,x1_max = x[:,0].min(),x[:,0].max()
    #得到第1列范围
    x2_min,x2_max = x[:,1].min(),x[:,1].max()
    t1 = np.linspace(x1_min,x1_max,N)
    t2 = np.linspace(x2_min,x2_max,M)
    #生成网格采样点
    x1,x2 = np.meshgrid(t1,t2)
    #测试点
    x_test = np.stack((x1.flat,x2.flat),axis=1)
    #预测值
    y_hat = logreg.predict(x_test)
    #使之与输入形状相同
    y_hat = y_hat.reshape(x1.shape)
    #预测值的显示
    plt.pcolormesh(x1,x2,y_hat,cmap=plt.cm.prism)
    plt.scatter(x[:,0],x[:,1],c=np.squeeze(y),edgecolors='k',cmap=plt.cm.prism)
    #显示样本
    plt.xlabel('Sepal length')
    plt.ylabel('Sepal width')
    plt.xlim(x1_min,x1_max)
    plt.ylim(x2_min,x2_max)
    plt.grid()
    plt.show()
    #训练集上的预测结果
    y_hat = logreg.predict(x)
    y = y.reshape(-1)
    print y_hat.shape
    print y.shape
    result = y_hat == y
    print y_hat
    print y
    print result
    c = np.count_nonzero(result)
    print c
    print 'Accuracy: %.2f%%' %(100*float(c)/float(len(result)))

2.2.3结果分析

(一)实验结果

(二)结果分析

1.仅仅使用两个特征:花萼长度和宽度,在150个样本中,有115个分类正确,正确率为76.67%。

2.当我们使用更多特征(4个特征全部使用),再次运行程序:

import numpy as np
from sklearn.linear_model import LogisticRegression
import matplotlib.pyplot as plt

def iris_type(s):
    it = {'Iris-setosa':0,'Iris-versicolor':1,'Iris-virginica':2}
    return it[s]

if __name__ == "__main__":
    path = 'iris.data'#数据文件路径
    #路径,浮点型数据,逗号分隔,第4列用函数iris_type单独处理
    data = np.loadtxt(path,dtype=float,delimiter=',',converters={4:iris_type})
    #将数据的0-3列组成x,第4列得到y
    x,y = np.split(data,(4,),axis=1)
    #为了可视化,仅使用前两列特征
    #x = x[:,:2]
    #Logistic回归模型
    logreg = LogisticRegression()
    #根据数据[x,y],计算回归参数
    logreg.fit(x,y.ravel())
    #画图
    #横纵各采样多少个值
    N,M,P,Q = 100,100,100,100
    #得到第0列范围
    x1_min,x1_max = x[:,0].min(),x[:,0].max()
    #得到第1列范围
    x2_min,x2_max = x[:,1].min(),x[:,1].max()
    #得到第2列范围
    x3_min,x3_max = x[:,2].min(),x[:,2].max()
    #得到第3列范围
    x4_min,x4_max = x[:,3].min(),x[:,3].max()
    t1 = np.linspace(x1_min,x1_max,N)
    t2 = np.linspace(x2_min,x2_max,M)
    t3 = np.linspace(x3_min,x3_max,P)
    t4 = np.linspace(x4_min,x4_max,Q)
    #生成网格采样点
    x1,x2,x3,x4 = np.meshgrid(t1,t2,t3,t4)
    #测试点
    x_test = np.stack((x1.flat,x2.flat,x3.flat,x4.flat),axis=1)
    #预测值
    y_hat = logreg.predict(x_test)
    #使之与输入形状相同
    y_hat = y_hat.reshape(x1.shape)
    #训练集上的预测结果
    y_hat = logreg.predict(x)
    y = y.reshape(-1)
    print y_hat.shape
    print y.shape
    result = y_hat == y
    print y_hat
    print y
    print result
    c = np.count_nonzero(result)
    print c
    print 'Accuracy: %.2f%%' %(100*float(c)/float(len(result)))

可以发现,在150个样本中,有144个分类正确,正确率为96.00%。

猜你喜欢

转载自blog.csdn.net/gengkui9897/article/details/83037099