Skip to content

Commit f035b59

Browse files
committed
添加回归的sklearn的demo和树回归的sklearn的demo
1 parent fdec203 commit f035b59

4 files changed

Lines changed: 281 additions & 20 deletions

File tree

src/python/8.Predictive numerical data regression/regression.py renamed to src/python/8.PredictiveNumericalDataRegression/regression.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def standRegres(xArr,yArr):
6666
# 书中的公式,求得w的最优解
6767
ws = xTx.I * (xMat.T*yMat)
6868
return ws
69-
69+
7070
# 局部加权线性回归
7171
def lwlr(testPoint,xArr,yArr,k=1.0):
7272
'''
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
#!/usr/bin/python
2+
# coding:utf8
3+
4+
'''
5+
Created on Jan 8, 2011
6+
Update on 2017-05-18
7+
@author: Peter Harrington/小瑶
8+
《机器学习实战》更新地址:https://github.com/apachecn/MachineLearning
9+
'''
10+
11+
12+
# Isotonic Regression 等式回归
13+
print(__doc__)
14+
15+
# Author: Nelle Varoquaux <nelle.varoquaux@gmail.com>
16+
# Alexandre Gramfort <alexandre.gramfort@inria.fr>
17+
# License: BSD
18+
19+
import numpy as np
20+
import matplotlib.pyplot as plt
21+
from matplotlib.collections import LineCollection
22+
23+
from sklearn.linear_model import LinearRegression
24+
from sklearn.isotonic import IsotonicRegression
25+
from sklearn.utils import check_random_state
26+
27+
n = 100
28+
x = np.arange(n)
29+
rs = check_random_state(0)
30+
y = rs.randint(-50, 50, size=(n,)) + 50. * np.log(1 + np.arange(n))
31+
32+
ir = IsotonicRegression()
33+
34+
y_ = ir.fit_transform(x, y)
35+
36+
lr = LinearRegression()
37+
lr.fit(x[:, np.newaxis], y) # 线性回归的 x 需要为 2d
38+
39+
segments = [[[i, y[i]], [i, y_[i]]] for i in range(n)]
40+
lc = LineCollection(segments, zorder=0)
41+
lc.set_array(np.ones(len(y)))
42+
lc.set_linewidths(0.5 * np.ones(n))
43+
44+
fig = plt.figure()
45+
plt.plot(x, y, 'r.', markersize=12)
46+
plt.plot(x, y_, 'g.-', markersize=12)
47+
plt.plot(x, lr.predict(x[:, np.newaxis]), 'b-')
48+
plt.gca().add_collection(lc)
49+
plt.legend(('Data', 'Isotonic Fit', 'Linear Fit'), loc='lower right')
50+
plt.title('Isotonic regression')
51+
plt.show()
52+
53+
# Kernel ridge regression ( 内核岭回归 )
54+
55+
# 2.1 Comparison of kernel ridge regression and SVR ( 内核岭回归与 SVR 的比较 )
56+
57+
# Authors: Jan Hendrik Metzen <jhm@informatik.uni-bremen.de>
58+
# License: BSD 3 clause
59+
60+
'''
61+
from __future__ import division
62+
import time
63+
64+
import numpy as np
65+
66+
from sklearn.svm import SVR
67+
from sklearn.model_selection import GridSearchCV
68+
from sklearn.model_selection import learning_curve
69+
from sklearn.kernel_ridge import KernelRidge
70+
import matplotlib.pyplot as plt
71+
72+
rng = np.random.RandomState(0)
73+
74+
# 生成样本数据
75+
X = 5 * rng.rand(10000, 1)
76+
y = np.sin(X).ravel()
77+
78+
# 给目标增加噪音
79+
y[::5] += 3 * (0.5 - rng.rand(X.shape[0] // 5))
80+
81+
X_plot = np.linspace(0, 5, 100000)[:, None]
82+
83+
# Fit regression model ( 拟合 回归 模型 )
84+
train_size = 100
85+
svr = GridSearchCV(SVR(kernel='rbf', gamma=0.1), cv=5,
86+
param_grid={"C": [1e0, 1e1, 1e2, 1e3],
87+
"gamma": np.logspace(-2, 2, 5)})
88+
89+
kr = GridSearchCV(KernelRidge(kernel='rbf', gamma=0.1), cv=5,
90+
param_grid={"alpha": [1e0, 0.1, 1e-2, 1e-3],
91+
"gamma": np.logspace(-2, 2, 5)})
92+
93+
t0 = time.time()
94+
svr.fit(X[:train_size], y[:train_size])
95+
svr_fit = time.time() - t0
96+
print("SVR complexity and bandwidth selected and model fitted in %.3f s"
97+
% svr_fit)
98+
99+
t0 = time.time()
100+
kr.fit(X[:train_size], y[:train_size])
101+
kr_fit = time.time() - t0
102+
print("KRR complexity and bandwidth selected and model fitted in %.3f s"
103+
% kr_fit)
104+
105+
sv_ratio = svr.best_estimator_.support_.shape[0] / train_size
106+
print("Support vector ratio: %.3f" % sv_ratio)
107+
108+
t0 = time.time()
109+
y_svr = svr.predict(X_plot)
110+
svr_predict = time.time() - t0
111+
print("SVR prediction for %d inputs in %.3f s"
112+
% (X_plot.shape[0], svr_predict))
113+
114+
t0 = time.time()
115+
y_kr = kr.predict(X_plot)
116+
kr_predict = time.time() - t0
117+
print("KRR prediction for %d inputs in %.3f s"
118+
% (X_plot.shape[0], kr_predict))
119+
120+
# 查看结果
121+
sv_ind = svr.best_estimator_.support_
122+
plt.scatter(X[sv_ind], y[sv_ind], c='r', s=50, label='SVR support vectors',
123+
zorder=2)
124+
plt.scatter(X[:100], y[:100], c='k', label='data', zorder=1)
125+
plt.hold('on')
126+
plt.plot(X_plot, y_svr, c='r',
127+
label='SVR (fit: %.3fs, predict: %.3fs)' % (svr_fit, svr_predict))
128+
plt.plot(X_plot, y_kr, c='g',
129+
label='KRR (fit: %.3fs, predict: %.3fs)' % (kr_fit, kr_predict))
130+
plt.xlabel('data')
131+
plt.ylabel('target')
132+
plt.title('SVR versus Kernel Ridge')
133+
plt.legend()
134+
135+
# 可视化训练和预测时间
136+
plt.figure()
137+
138+
# 生成样本数据
139+
X = 5 * rng.rand(10000, 1)
140+
y = np.sin(X).ravel()
141+
y[::5] += 3 * (0.5 - rng.rand(X.shape[0] // 5))
142+
sizes = np.logspace(1, 4, 7, dtype=np.int)
143+
for name, estimator in {"KRR": KernelRidge(kernel='rbf', alpha=0.1,
144+
gamma=10),
145+
"SVR": SVR(kernel='rbf', C=1e1, gamma=10)}.items():
146+
train_time = []
147+
test_time = []
148+
for train_test_size in sizes:
149+
t0 = time.time()
150+
estimator.fit(X[:train_test_size], y[:train_test_size])
151+
train_time.append(time.time() - t0)
152+
153+
t0 = time.time()
154+
estimator.predict(X_plot[:1000])
155+
test_time.append(time.time() - t0)
156+
157+
plt.plot(sizes, train_time, 'o-', color="r" if name == "SVR" else "g",
158+
label="%s (train)" % name)
159+
plt.plot(sizes, test_time, 'o--', color="r" if name == "SVR" else "g",
160+
label="%s (test)" % name)
161+
162+
plt.xscale("log")
163+
plt.yscale("log")
164+
plt.xlabel("Train size")
165+
plt.ylabel("Time (seconds)")
166+
plt.title('Execution Time')
167+
plt.legend(loc="best")
168+
169+
# 可视化学习曲线
170+
plt.figure()
171+
172+
svr = SVR(kernel='rbf', C=1e1, gamma=0.1)
173+
kr = KernelRidge(kernel='rbf', alpha=0.1, gamma=0.1)
174+
train_sizes, train_scores_svr, test_scores_svr = \
175+
learning_curve(svr, X[:100], y[:100], train_sizes=np.linspace(0.1, 1, 10),
176+
scoring="neg_mean_squared_error", cv=10)
177+
train_sizes_abs, train_scores_kr, test_scores_kr = \
178+
learning_curve(kr, X[:100], y[:100], train_sizes=np.linspace(0.1, 1, 10),
179+
scoring="neg_mean_squared_error", cv=10)
180+
181+
plt.plot(train_sizes, -test_scores_svr.mean(1), 'o-', color="r",
182+
label="SVR")
183+
plt.plot(train_sizes, -test_scores_kr.mean(1), 'o-', color="g",
184+
label="KRR")
185+
plt.xlabel("Train size")
186+
plt.ylabel("Mean Squared Error")
187+
plt.title('Learning curves')
188+
plt.legend(loc="best")
189+
190+
plt.show()
191+
'''

src/python/9.RegTrees/regTrees.py

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Created on Feb 4, 2011
55
Update on 2017-05-18
66
Tree-Based Regression Methods Source Code for Machine Learning in Action Ch. 9
7-
@author: Peter Harrington/片刻
7+
@author: Peter Harrington/片刻/小瑶
88
《机器学习实战》更新地址:https://github.com/apachecn/MachineLearning
99
'''
1010
print(__doc__)
@@ -15,7 +15,7 @@
1515
# general function to parse tab -delimited floats
1616
def loadDataSet(fileName):
1717
"""loadDataSet(解析每一行,并转化为float类型)
18-
18+
Desc:该函数读取一个以 tab 键为分隔符的文件,然后将每行的内容保存成一组浮点数
1919
Args:
2020
fileName 文件名
2121
Returns:
@@ -30,21 +30,22 @@ def loadDataSet(fileName):
3030
curLine = line.strip().split('\t')
3131
# 将所有的元素转化为float类型
3232
# map all elements to float()
33+
# map() 函数具体的含义,可见 https://my.oschina.net/zyzzy/blog/115096
3334
fltLine = map(float, curLine)
3435
dataMat.append(fltLine)
3536
return dataMat
3637

3738

3839
def binSplitDataSet(dataSet, feature, value):
3940
"""binSplitDataSet(将数据集,按照feature列的value进行 二元切分)
40-
41+
Description:在给定特征和特征值的情况下,该函数通过数组过滤方式将上述数据集合切分得到两个子集并返回。
4142
Args:
4243
dataMat 数据集
43-
feature 特征列
44+
feature 待切分的特征列
4445
value 特征列要比较的值
4546
Returns:
46-
mat0 小于的数据集在左边
47-
mat1 大于的数据集在右边
47+
mat0 小于等于 value 的数据集在左边
48+
mat1 大于 value 的数据集在右边
4849
Raises:
4950
"""
5051
# # 测试案例
@@ -61,11 +62,13 @@ def binSplitDataSet(dataSet, feature, value):
6162

6263
# 返回每一个叶子结点的均值
6364
# returns the value used for each leaf
65+
# 我的理解是:regLeaf 是产生叶节点的函数,就是求均值,即用聚类中心点来代表这类数据
6466
def regLeaf(dataSet):
6567
return mean(dataSet[:, -1])
6668

6769

6870
# 计算总方差=方差*样本数
71+
# 我的理解是:求这组数据的方差,即通过决策树划分,可以让靠近的数据分到同一类中去
6972
def regErr(dataSet):
7073
# shape(dataSet)[0] 表示行数
7174
return var(dataSet[:, -1]) * shape(dataSet)[0]
@@ -80,18 +83,23 @@ def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
8083
dataSet 加载的原始数据集
8184
leafType 建立叶子点的函数
8285
errType 误差计算函数(求总方差)
83-
ops [容许误差下降值,切分的最少样本数]
86+
ops [容许误差下降值,切分的最少样本数]
8487
Returns:
8588
bestIndex feature的index坐标
8689
bestValue 切分的最优值
8790
Raises:
8891
"""
92+
93+
# ops=(1,4),非常重要,因为它决定了决策树划分停止的threshold值,被称为预剪枝(prepruning),其实也就是用于控制函数的停止时机。
94+
# 之所以这样说,是因为它防止决策树的过拟合,所以当误差的下降值小于tolS,或划分后的集合size小于tolN时,选择停止继续划分。
95+
# 最小误差下降值,划分后的误差减小小于这个差值,就不用继续划分
8996
tolS = ops[0]
97+
# 划分最小 size 小于,就不继续划分了
9098
tolN = ops[1]
91-
# 如果结果集(最后一列为1个变量),就返回推出
99+
# 如果结果集(最后一列为1个变量),就返回退出
92100
# .T 对数据集进行转置
93101
# .tolist()[0] 转化为数组并取第0列
94-
if len(set(dataSet[:, -1].T.tolist()[0])) == 1:
102+
if len(set(dataSet[:, -1].T.tolist()[0])) == 1: # 如果集合size为1,不用继续划分。
95103
# exit cond 1
96104
return None, leafType(dataSet)
97105
# 计算行列值
@@ -102,7 +110,7 @@ def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
102110
# inf 正无穷大
103111
bestS, bestIndex, bestValue = inf, 0, 0
104112
# 循环处理每一列对应的feature值
105-
for featIndex in range(n-1):
113+
for featIndex in range(n-1): # 对于每个特征
106114
# [0]表示这一列的[所有行],不要[0]就是一个array[[所有行]]
107115
for splitVal in set(dataSet[:, featIndex].T.tolist()[0]):
108116
# 对该列进行分组,然后组内的成员的val值进行 二元切分
@@ -112,6 +120,7 @@ def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
112120
continue
113121
newS = errType(mat0) + errType(mat1)
114122
# 如果二元切分,算出来的误差在可接受范围内,那么就记录切分点,并记录最小误差
123+
# 如果划分后误差小于 bestS,则说明找到了新的bestS
115124
if newS < bestS:
116125
bestIndex = featIndex
117126
bestValue = splitVal
@@ -122,15 +131,17 @@ def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
122131
return None, leafType(dataSet)
123132
mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue)
124133
# 对整体的成员进行判断,是否符合预期
125-
if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN):
134+
# 如果集合的 size 小于 tolN
135+
if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): # 当最佳划分后,集合过小,也不划分,产生叶节点
126136
return None, leafType(dataSet)
127137
return bestIndex, bestValue
128138

129139

130140
# assume dataSet is NumPy Mat so we can array filtering
141+
# 假设 dataSet 是 NumPy Mat 类型的,那么我们可以进行 array 过滤
131142
def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
132143
"""createTree(获取回归树)
133-
144+
Description:递归函数:如果构建的是回归树,该模型是一个常数,如果是模型树,其模型师一个线性方程。
134145
Args:
135146
dataSet 加载的原始数据集
136147
leafType 建立叶子点的函数
@@ -143,14 +154,15 @@ def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1, 4)):
143154
# choose the best split
144155
feat, val = chooseBestSplit(dataSet, leafType, errType, ops)
145156
# if the splitting hit a stop condition return val
157+
# 如果 splitting 达到一个停止条件,那么返回 val
146158
if feat is None:
147159
return val
148160
retTree = {}
149161
retTree['spInd'] = feat
150162
retTree['spVal'] = val
151163
# 大于在右边,小于在左边,分为2个数据集
152164
lSet, rSet = binSplitDataSet(dataSet, feat, val)
153-
# 递归的进行调用
165+
# 递归的进行调用,在左右子树中继续递归生成树
154166
retTree['left'] = createTree(lSet, leafType, errType, ops)
155167
retTree['right'] = createTree(rSet, leafType, errType, ops)
156168
return retTree
@@ -318,14 +330,14 @@ def createForeCast(tree, testData, modelEval=regTreeEval):
318330
# myTree = createTree(myMat, modelLeaf, modelErr)
319331
# print myTree
320332

321-
# 回归树 VS 模型树 VS 线性回归
333+
# # 回归树 VS 模型树 VS 线性回归
322334
trainMat = mat(loadDataSet('input/9.RegTrees/bikeSpeedVsIq_train.txt'))
323335
testMat = mat(loadDataSet('input/9.RegTrees/bikeSpeedVsIq_test.txt'))
324-
# 回归树
325-
myTree1 = createTree(trainMat, ops=(1, 20))
326-
print myTree1
327-
yHat1 = createForeCast(myTree1, testMat[:, 0])
328-
print "回归树:", corrcoef(yHat1, testMat[:, 1],rowvar=0)[0, 1]
336+
# # 回归树
337+
# myTree1 = createTree(trainMat, ops=(1, 20))
338+
# print myTree1
339+
# yHat1 = createForeCast(myTree1, testMat[:, 0])
340+
# print "回归树:", corrcoef(yHat1, testMat[:, 1],rowvar=0)[0, 1]
329341

330342
# 模型树
331343
myTree2 = createTree(trainMat, modelLeaf, modelErr, ops=(1, 20))

0 commit comments

Comments
 (0)