3、预测模型笔记

预测模型

1、简介

预测建模(Predictive modeling)是一种用来预测系统未来行为的分析技术,它由一群能够识别独立输入变量与反馈目标关联关系的算法构成。根据观测值创建一个数学模型,然后用这个模型去预测未来发生的事情。
预测模型是用若干个可能对系统行为产生影响的特征构建的,当处理系统问题时,需要先判断哪些因素可能会影响系统的行为,然后在训练模型之前将这些因素添加进特征中。

2、用SVM建立线性分类器

SVM是用来构建分类器和回归器的监督学习模型,SVM通过对数学方程组求解,可以找出两组数据之间的最佳分割边界。下面先使用第2章的创建简单分类器将数据分类并画出。

# 1、加载数据
import numpy as np
import matplotlib.pyplot as plt
input_file = 'data_multivar.txt'

def load_data(input_file):
    X = []
    y = []
    with open(input_file, 'r') as f:
        for line in f.readlines():
            data = [float(x) for x in line.split(',')]
            X.append(data[:-1])
            y.append(data[-1])
    X=np.array(X)
    y = np.array(y)
    return X,y
X,y=load_data(input_file)

# 2、分类
class_0=np.array([X[i] for i in range(len(X)) if y[i]==0])
class_1=np.array([X[i] for i in range(len(X)) if y[i]==1])
print(class_0)
# 3、画图
plt.figure()
plt.scatter(class_0[:,0],class_0[:,1],facecolor='black',edgecolors='black',marker='s')
plt.scatter(class_1[:,0],class_1[:,1],facecolor='none',edgecolors='black',marker='s')
plt.show()

# 定义画图函数
def plot_classifier(classifier, X, y):
    # 获取x,y的最大最小值,并设置余值
    x_min, x_max = min(X[:, 0]) - 1.0, max(X[:, 0] + 1.0)
    y_min, y_max = min(X[:, 1]) - 1.0, max(X[:, 1] + 1.0)
    # 设置网格步长
    step_size = 0.01
    # 设置网格
    x_values, y_values = np.meshgrid(np.arange(x_min, x_max, step_size), np.arange(y_min, y_max, step_size))
    # 计算出分类器的分类结果
    mesh_output = classifier.predict(np.c_[x_values.ravel(), y_values.ravel()])
    mesh_output = mesh_output.reshape(x_values.shape)
    # 画图
    plt.figure()
    # 选择配色方案
    plt.pcolormesh(x_values, y_values, mesh_output, cmap=plt.cm.gray)
    # 画点
    plt.scatter(X[:, 0], X[:, 1], c=y, s=80, edgecolors='black', linewidths=1, cmap=plt.cm.Paired)
    # 设置图片取值范围
    plt.xlim(x_values.min(), x_values.max())
    plt.ylim(y_values.min(), y_values.max())
    # 设置x与y轴
    plt.xticks((np.arange(int(min(X[:, 0]) - 1), int(max(X[:, 0]) + 1), 1.0)))
    plt.yticks((np.arange(int(min(X[:, 1]) - 1), int(max(X[:, 1]) + 1), 1.0)))
    plt.show()

如图:

从上面的结果可以看出,空心和实心分别为不同类。下面使用SVM将不同类分开。结果如下图:


代码如下:

# 使用SVM
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=5)
params = {'kernel': 'linear'}
classifier = SVC(**params)
# 训练线性SVM分类器,并查看结果边界
classifier.fit(X_train, y_train)
plot_classifier(classifier, X_train, y_train)
# 测试数据集
y_test_pred = classifier.predict(X_test)
plot_classifier(classifier, X_test, y_test)
# 查看数据的精准性,训练数据集的分类报告
from sklearn.metrics import classification_report
print(classification_report(y_train,classifier.predict(X_train),target_names=['Class-'+str(int(i)) for i in set(y)]))
# 测试数据集的分类报告
print(classification_report(y_test,classifier.predict(X_test),target_names=['Class-'+str(int(i)) for i in set(y)]))

3、用SVM建立非线性分类器

从上面的分类报告可知,我们的分类情况并不理想,而且,最开始的数据可视化也可看出,实心完全被空心包围着,所以,我们需要尝试非线性分类器。
SVM为建立非线性分类器提供了许多选项,需要用不同的核函数建立费线性分类器。为了简单起见,考虑一下两种情况。

3.1、多项式函数

直接将线性中的params={'kernel':'linear'}替换成params={'kernel':'poly','degree':3},其中degree表示三次多项式,随着次数增加,可让曲线变得更弯,但是训练时间也会越长,计算强度越大。结果如下图:

3.2、径向基函数(Radial Basis Function,RBF)

直接将线性中的params={'kernel':'linear'}替换成params={'kernel':'rbf'},结果如下图:

4、解决类型数量不平衡问题

在现实生活中,我们得到的数据可能会出现某类数据比其他类型数据多很多的情况,在这种情况下分类器会有偏差,边界线也不会反应数据的真实性,所以需要对数据进行调和。
换一个数据,以上面线性SVM为例,将数据换成data_multivar_imbalance.txt之后,显示为

由图可知,没有边界线,这是因为分类器不能区分这两种类型,所以,将参数改为params={'kernel':'linear','class_weight':'balanced'}即可。结果如下:

5、提取置信度

当一个信的数据点被分类为某一个已知类别时,我们可训练SVM来计算输出类型的置信度。

input_datapoints = np.array([[2, 1.5], [8, 9], [4.8, 5.2], [4, 4], [2.5, 7], [7.6, 2], [5.4, 5.9]])

for i in input_datapoints:
    print(i, '-->', classifier.decision_function(i)[0])# 测量点到边界的距离

params = {'kernel': 'rbf', 'probability': True}
classifier = SVC(**params)
classifier.fit(X_train, y_train)

for i in input_datapoints:
    print(i, '-->', classifier.predict_proba(i)[0])# 这里要求params中probability必须为True,计算输入数据点的置信度

plot_classifier(classifier, input_datapoints, [0]*len(input_datapoints))

6、寻找最优超参数

超参数对分类器的性能至关重要。寻找步骤如下:

# 1、加载数据,通过交叉验证
parameter_grid = [{'kernel': ['linear'], 'C': [1, 10, 50, 600]},
                  {'kernel': ['poly'], 'degree': [2, 3]},
                  {'kernel': ['rbf'], 'gamma': [0.01, 0.001], 'C': [1, 10, 50, 600]},
                  ]

metrics = ['precision', 'recall_weighted']

from sklearn import svm, grid_search, cross_validation
from sklearn.metrics import classification_report
# 2、为每个指标搜索最优超参数
for metric in metrics:
    classifier = grid_search.GridSearchCV(svm.SVC(C=1), parameter_grid, cv=5, scoring=metric)# 获取对象
    classifier.fit(X_train, y_train)# 训练
    for params, avg_score, _ in classifier.grid_scores_:# 看指标得分
        print(params, '-->', round(avg_score, 3))
    print('最好参数集:',classifier.best_params_)# 最优参数集
    y_true, y_pred = y_test, classifier.predict(X_test)
    print(classification_report(y_true, y_pred))# 打印一下性能报告

7、建立时间预测器

这个例子和之前的差不多,主要是记住步骤。

# 1、读取数据
input_file='building_event_multiclass.txt'
# input_file='building_event_binary.txt'

X=[]
y=[]
with open(input_file,'r') as f:
    for line in f.readlines():
        data=line[:-1].split(',')
        X.append([data[0]]+data[2:])
X=np.array(X)
# 2、编码器编码
from sklearn import preprocessing
label_encoder=[]
X_encoder=np.empty(X.shape)
for i,item in enumerate(X[0]):
    if item.isdigit():
        X_encoder[:,i]=X[:,i]
    else:
        label_encoder.append(preprocessing.LabelEncoder())
        X_encoder[:,i]=label_encoder[-1].fit_transform(X[:,i])
X=np.array(X_encoder[:,:-1]).astype(int)
y=np.array(X_encoder[:,-1]).astype(int)
# 3、进行分类
from sklearn.svm import SVC
params={'kernel':'rbf','probability':True,'class_weight':'balanced'}
classifier=SVC(**params)
classifier.fit(X,y)
# 4、交叉验证
from sklearn.model_selection import cross_val_score
accuracy=cross_val_score(classifier,X,y,scoring='accuracy',cv=3)
print('accuracy:',accuracy.mean())
# 5、对新数据进行验证
input_data = ['Tuesday', '12:30:00','21','23']
input_data_encoder=[-1]*len(input_data)
count=0

for i,item in enumerate(input_data):
    if item.isdigit():
        input_data_encoder[i]=int(input_data[i])
    else:
        label=[]
        label.append(input_data[i])
        input_data_encoder[i]=label_encoder[count].transform(label)
        count=count+1

result=int(classifier.predict(np.array(input_data_encoder)))
print('result:',label_encoder[-1].inverse_transform(result))

8、估算交通流量

在之前的SVM都是用作分类器,现在展示一个回归器的例子:

# 1、获取数据
X=[]
input_file='traffic_data.txt'
with open(input_file,'r') as f:
    for line in f.readlines():
        data=line[:-1].split(',')
        X.append(data)

X=np.array(X)

# 2、编码
from sklearn import preprocessing
label_encoder=[]
X_encoder=np.empty(X.shape)
for i,item in enumerate(X[0]):
    if item.isdigit():
        X_encoder[:,i]=X[:,i]
    else:
        label_encoder.append(preprocessing.LabelEncoder())
        X_encoder[:,i]=label_encoder[-1].fit_transform(X[:,i])

X=X_encoder[:,:-1].astype(int)
y=X_encoder[:,-1].astype(int)

# 3、线性回归
from sklearn.svm import SVR
# params = {'kernel': 'rbf', 'C': 10.0, 'epsilon': 0.2}
params={'kernel':'rbf','C':10.0,'epsilon':0.2}# C表示对分类的惩罚,参数epsilon表示不使用惩罚的限制
regressor=SVR(**params)
regressor.fit(X,y)
# 4、验证
from sklearn.metrics import mean_absolute_error
y_pred=regressor.predict(X)
print('mean_absolute_error:',mean_absolute_error(y,y_pred))
# 5、预测新值
input_data = ['Tuesday', '13:35', 'San Francisco', 'yes']
input_data_encoder=[-1]*len(input_data)
count=0
for i,item in enumerate(input_data):
    if item.isdigit():
        input_data_encoder[i]=int(input_data[i])
    else:
        label=[]
        label.append(input_data[i])
        input_data_encoder[i]=int(label_encoder[count].transform(label))
        count=count+1
        
result=regressor.predict(input_data_encoder)
print(result)
posted @ 2018-01-12 23:55  NSGUF  阅读(681)  评论(0编辑  收藏  举报