我们前面介绍了树回归中的回归树和模型树 两种回归方式。
本节我们首先将树回归和标准回归进行比较,然后创建出一个GUI,通过交互的形式更好去观察模型树和回归树之间的奥秘。
1. 树回归与标准回归的比较
我们之前介绍过几种回归模型,为了比较哪种模型更好?一个比较客观的方法就是计算相关系数(
R2
值)。该相关系数可以直接去调用Numpy库中的corrcoef(yHat, y, rowvar=0)来直接求解,其中yhat是预测值,y是实际值。
这里先通过一些函数实现给定输入进行预测,之后利用这些函数计算三种回归模型的回归误差,最后调用corrcoef来比较相关系数。
# 用树回归进行预测
def regTreeEval(model, inDat):
"""
回归树,为了和模型数函数参数一致,我们输入两个参数,但是只使用一个.
model为输入叶节点
"""
return float(model)
def modeltreeEval(model, inDat):
'模型树'
n = np.shape(indat)[1] # 输入测试数据的列数
X = np.mat(np.ones((1, n+1)))
X[:, 1:n+1] = inDat
return float(X * model)
def treeForeCast(tree, inData, modelEval=regTreeEval):
"""
在给定树结构下,对于输入的单个数据点或者行向量,返回预测值。
最后一个参数是指明对叶节点数据进行预测函数的引用(回归数或模型数)
"""
if not isTree(tree):
modelEval(tree, inData) # 如果不是树结构,就进行预测。
if inData[tree['spInd']] > tree['spVal']:
# 二元切分,阈值两边,一个走左子树,一个走右子树
if isTree(tree['left']):
return treeForeCast(tree['left'], inData, modelEval)
else:
return modelEval(tree['left'], inData)
else:
if isTree(tree['right']):
return treeForeCast(tree['right'], inData, modelEval)
else:
return modelEval(tree['right'], inData)
def createForeCast(tree, testData, modelEval=regTreeEval):
"""
实现整个预测集上的运算
"""
m = len(testData)
yHat = np.mat(np.zeros((m, 1)))
for i in range(m):
yHat[i, 0] = treeForeCast(tree, np.mat(testData[i]), modelEval)
return yHat
结果为::
我们知道相关系数越接近1越好,显然,模型树这一模型相比其他两个模型更好。
回归树,模型树的代码:
链接:http://pan.baidu.com/s/1slKsKXJ 密码:2ez4
2. 图形用户界面编程-Thinter的介绍
在回归树模型中,不同的参数ops,会有不同的树结构。但是每次在代码中手动调节ops,使得结果的分析显得困难。因此我们可以通过GUI来同时呈现数据和支持用户交互来更便捷的分析结果,也就是图形用户界面编程(GUI)。
Python默认的GUI工具集是Tk,我们可以通过Python接口Tkinter来使用Tk。Tkinter是Python默认的GUI库,它基于Tk工具集,后者最初是为工具命令语言(Tcl)设计的。
安装 Tkinter模块: 请参考 http://blog.csdn.net/xyqzki/article/details/38414433
2.1 Tkinter与Python编程
要创建并运行你的GUI程序,下面有5个基本步骤:
1 导入Tkinter模块
2 创建一个顶层窗口对象,来容纳你的整个GUI程序
3 在你的顶层窗口对象上(或者其中)创建所有的GUI模块(以及功能)
4 把这些GUI模块与底层代码相连接
5 进入主事件循环
在开始逐步介绍前,我们先从宏观上介绍下GUI程序开发。
在GUI程序中,会有一个顶层根窗口对象,它包含所有小窗口对象。它们共同构成了一个完整的GUI程序,(这些小窗口对象可以是文字标签、按钮、列表框等),这些独立的GUI构件称为:组件
所以在创建GUI程序时,首先要创建一个顶层窗口,这实际上是指需要一个放置所有组件的地方:
注 Python3.3版本 改成tkinter
import tkinter
top = tkinter.Tk()
其中,tkinter.Tk()返回的对象通常被称为根窗口。顶层窗口是指那些在程序中独立显示的部分,可以创建多个底层窗口,但是只有一个是根窗口。
组件: 可以是独立的也可以作为容器存在。如果一个组件包含其他组件,它就可以认为是这些组件的父组件。通常组件会有一些相应的行为,如按下按钮,文本款写入等。这种形式的用户行为被称为行为事件,而GUI程序对时间所采取的响应动作被称为回调。
用户操作从系统角度看都可以被看作是事件,GUI程序则是由这些伴随其始末的整套事件·体系所驱动,这个过程被称为事件驱动处理。
Tk有两个坐标管理器用来协助吧组件放在正确的位置上:(1)‘包’:packer (2)网格:grid
一旦决定好所有组件的尺寸和尺寸方式,它将为你在屏幕上放置他们。当这些组件(包括顶层窗口)最终显示在屏幕上时,GUI程序会进入一个“服务器式”的无限循环。这个无限循环包括等待GUI事件、处理事件、然后返回等待模式。等待下一个事件。对Tkinter而言:
tkinter.mainloop()
这通常是程序执行的最后一段代码。
2.2 Tk组件
我们前面提到所有的主要组件都建立在顶层窗口对象内。这个对象是由Tk类创建的。Tk目前有15种组件。
实例1
#! -*- coding: utf-8 -*-
"""
创建一个标签显示“hello world!”
"""
import tkinter as tk
top =tk.Tk() # 创建一个顶层窗口
label = tk.Label(top, text='hello world!') # 创建标签
label.pack() # 指明用packer来管理和显示组件
tk.mainloop() #调用mainloop运行GUI程序
实例2
#! /usr/bin/env python
# -*- coding : utf-8 -*-
import tkinter as tk
top = tk.Tk()
quit = tk.Button(top, text='hello world!', command=top.quit)
#创建按钮组件,有一个额外的参数: tk.quit()方法,这将给按钮装一个回调函数。按钮按下(并释放后)整个程序退出
quit.pack()
tk.mainloop()
实例3
#! -*- coding: utf-8 -*-
"""
组合实例1和2
"""
import tkinter as tk
top =tk.Tk() # 创建一个顶层窗口
label = tk.Label(top, text='hello world!') # 创建标签
label.pack() # 指明用packer来管理和显示组件
quit1 = tk.Button(top, text='QUIT1', command=top.quit, bg='red', fg='white') # 参数添加了背景和前景颜色
quit1.pack() # fill参数告诉packer让QUIT按钮填充水平方向的剩余空间 expand填充了水平方向的所有可视空间,并拉伸按钮到窗口的左右边界
quit2 = tk.Button(top, text='QUIT2', command=top.quit, bg='red', fg='white')
quit2.pack(fill="x")
quit3 = tk.Button(top, text='QUIT3', command=top.quit, bg='red', fg='white')
quit3.pack(fill="x", expand=0)
quit3_1 = tk.Button(top, text='QUIT3_1', command=top.quit, bg='red', fg='white')
quit3_1.pack(fill="x", expand=1)
quit4 = tk.Button(top, text='QUIT4', command=top.quit, bg='red', fg='white')
quit4.pack(fill="y", expand=1)
quit5 = tk.Button(top, text='QUIT5', command=top.quit, bg='red', fg='white')
quit5.pack(fill="both", expand=0)
quit6 = tk.Button(top, text='QUIT6', command=top.quit, bg='red', fg='white')
quit6.pack(fill="both", expand=1)
tk.mainloop() #调用mainloop运行GUI程序
分析:(pack 不同参数的效果)
当 expand全为0时:
当 expand全为1时:
对比全0和全1的结果,可知:
(1)expand默认值为0,(不使用额外的空间即其余的空白)
(2) 为0: 不用额外空间,都是最小的区域,只是在不同方向填充,从上到下排列
(3)为1(除 QUIT1): 使用额外的空间,随着我们拉动窗口,始终填满窗口
再看代码中的结果:
QUIT1 : pack() 全部默认参数,大小为容纳这个组件的最小区域。
QUIT2 : 在x方向填充,不使用额外空间
QUIT3 : 在x方向填充,不使用额外空间
QUIT3-1 : 在x方向填充,使用额外空间
QUIT4 : 在y方向填充,使用额外空间
QUIT5 : 在x,y方向都填充,不使用额外空间
QUIT6 : 在x,y方向都填充,使用额外空间
实例4
# 拖动滚动条,字体大小变化
import tkinter as tk
def resize(ev=None): # 自己创建 回调函数
label.config(font='Helvetica -%d bold' % scale.get()) # 设置Label文字的字体,字体大小为 scale滚动条的数字
top = tk.Tk()
top.geometry('960x540') # 设置顶层窗口大小
label = tk.Label(top, text='Hello World!', font='Helvetica -18 bold')
label.pack(fill="y", expand=1)
scale = tk.Scale(top, from_=10, to=50, orient="horizontal", command=resize)
#设置开始和结束值 注意from_的使用方式,在其后添加了"_",避免与关键字from的冲突'
#orient可能值为: horizontal or vertical
#回调函数
scale.set(10)
scale.pack(fill="x")
tk.mainloop()
3. 实例(回归)来体验GUI
在下一篇介绍