Python 开发windows GUI程序是比较简单的,并且相比于C++学习成本比较低,并且其效果也不错。常用的Python GUI框架有: Tkinter,Wxpython,Pygtk,Pyqt,Pyside,Kivy。在这里基于我个人推荐的话建议认真学习Pyqt和Kivy(我自己仅熟悉这两个),下面我们先简单的介绍一下这几个Python GUI框架,然后基于一个最简单的机器学习模型,实现一个基于GUI的机器学习应用。

1.Python GUI框架介绍

Tkinter: 是Python内嵌的GUI环境,使用TCL实现,其中Python IDLE 就是由Tkinter实现,其发展历史比较悠久,并且在Python的标准安装包中就包含了Tkinter,易学易用,跨平台,听说实现出的效果比较简陋(关键靠人)

Wxpython:由C++编写,跨平台,说明文档比较少,学起来有些费劲。

PyGTK: Python对GTK + GUI库的封装,GTK在Windows下的兼容性会有一定的问题

Pyqt: QT是由C++实现的,Pyqt是Python对QT的包装,跨平台性能好,并且Pyqt与QT的函数接口一致,QT的开发文档相当丰富,导致Pyqt的开发文档也是很丰富(我们下面会使用Pyqt5实现)

Pyside: 同时也是Python对QT的封装,与Pyqt的API是一致的(还是直接Pyqt吧)

Kivy: 使用Python与cpython编写,可以做移动端设备的APP开发,主要针对多点触摸应用,支持Android和ios,布局设置时可以使用Kivy Language,好像也有类似于Qt Designer的kivy-designer(个人感觉不大好用,我一般直接垒Kivy语言)

那么本小项目我们使用Pyqt5做GUI的开发,原因很简单,简单易学,API和QT一致,开发文档丰富(遇到问题好解决),使用Qt designer实现直观布局设置,同时也方便打包发布软件。

可以在Qt designer上设计你的UI界面了。

2.首先来一个简单的ML model

在这里我们为了说明问题仅使用一个最简单的机器学习model,假设我是美国一家房产中介的数据分析师,Leader要求我构建一个房产定价模型(如果按照下面方式去建模,估计我会被炒,这里只是假设,你就当故事听就OK了)。首先我们要有数据,假设这个数据就是著名的波士顿房价数据(这里就不介绍这个公共数据集了,你可以百度或Google获得详细的解释或在R,Python中看到这个公共数据集的说明),我要构建几个价格预测模型,供客户选择,这里我就构建6种回归模型(假设使我们精挑细选训练的):简单的线性回归,岭回归,Lasso回归,K近邻回归,回归树,支持向量机回归,加载数据和训练的代码如下:

# step0:加载必要的模型
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

import sklearn.datasets as datasets
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import Ridge
from sklearn.linear_model import Lasso
from sklearn.neighbors import KNeighborsRegressor
from sklearn.tree import DecisionTreeRegressor
from sklearn.svm import SVR
from sklearn.model_selection import train_test_split
from sklearn.externals import joblib

# step1:数据获取

boston = datasets.load_boston()
train = boston.data
target = boston.target

X_train,x_test,y_train,y_true = train_test_split(train,target,test_size=0.2)
print(X_train,x_test)
print(y_train,y_true)

# step2: 初始化model
LR = LinearRegression()
RR= Ridge()
LLR = Lasso()
KNNR = KNeighborsRegressor()
DR = DecisionTreeRegressor()
SVMR = SVR()

# step3: Train and save and predict Model
# 这里省略了模型训练中评价和调参的过程
# 假设这就是美国房产中介Leader要我训练的
# 最终Model

LR.fit(X_train,y_train)
RR.fit(X_train,y_train)
LLR.fit(X_train,y_train)
KNNR.fit(X_train,y_train)
DR.fit(X_train,y_train)
SVMR.fit(X_train,y_train)

# 模型保存与持久化

joblib.dump(LR, "LR_model.m")
joblib.dump(RR, "RR_model.m")
joblib.dump(LLR, "LLR_model.m")
joblib.dump(KNNR, "KNNR_model.m")
joblib.dump(DR, "DR_model.m")
joblib.dump(SVMR, "SVMR_model.m")

# 模型加载
lr_m = joblib.load("LR_model.m")
rr_m = joblib.load("RR_model.m")
llr_m = joblib.load("LLR_model.m")
knnr_m = joblib.load("KNNR_model.m")
dr_m = joblib.load("DR_model.m")
svmr_m = joblib.load("SVMR_model.m")

y_LR = lr_m.predict(x_test)
y_RR = rr_m.predict(x_test)
y_LLR = llr_m.predict(x_test)
y_KNNR = knnr_m.predict(x_test)
y_DR = dr_m.predict(x_test)
y_SVMR = svmr_m.predict(x_test)

model_pre = pd.DataFrame({'LinearRegression()':list(y_LR),'Ridge()':list(y_RR),'Lasso()':list(y_LLR),
   'KNeighborsRegressor()':list(y_KNNR),'DecisionTreeRegressor()':list(y_DR),
   'SVR()':list(y_SVMR)})

# Plot

def model_plot(y_true,model_pre):
   '''
   y_true:真实的label
   model_pre: 预测的数据(数据框)
   '''
   cols = model_pre.columns
   plt.style.use("ggplot")
   plt.figure(figsize=(24,24))
   for i in range(6):
       plt.subplot(2,3,i+1)
       plt.scatter(x=range(len(y_true)),y=y_true,label='true')
       plt.scatter(x=range(len(model_pre[cols[i]])),y=model_pre[cols[i]],label=cols[i])
       
       plt.legend()

plt.savefig("model_plot.png")

model_plot(y_true, model_pre)

训练好的模型要交给每一个业务人员使用,但是我们不能每一个员工都要安装一个Python然后,叫他们怎样处理数据跑代码吧?(这显然是不行的)可以把保存好的Model做成一个带GUI的小工具,下面我们就把训练好的模型和Pyqt结合,做成一个带有UI界面的exe可执行文件,这样使用者就可以仅安装拷贝这个exe文件就可以使用模型做分析预测。

3.GUI封装Model

使用Pyqt5这个框架,把机器学习模型和GUI结合在一起,我直接上代码和最终呈现方式了,详细的源码可以去我下文提到的地址中下载,下面看一下涉及整个项目的文件:

渲染UI的代码

class Ui_MainWindow(object):
   def setupUi(self, MainWindow):
       MainWindow.setObjectName("MainWindow")
       MainWindow.resize(930, 600)
       icon = QtGui.QIcon()
       icon.addPixmap(QtGui.QPixmap(":/my_pic/pic/kh.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
       MainWindow.setWindowIcon(icon)
       self.centralWidget = QtWidgets.QWidget(MainWindow)
       self.centralWidget.setObjectName("centralWidget")
       self.groupBox = QtWidgets.QGroupBox(self.centralWidget)
       self.groupBox.setGeometry(QtCore.QRect(20, 20, 191, 161))
       self.groupBox.setObjectName("groupBox")
       self.pushButton = QtWidgets.QPushButton(self.groupBox)
       self.pushButton.setGeometry(QtCore.QRect(20, 30, 151, 31))
       self.pushButton.setFixedHeight(40)  
       self.pushButton.setStyleSheet("QPushButton{color:white;background:LimeGreen;border-radius:20px;border:3px solid black;}")
       icon1 = QtGui.QIcon()
       icon1.addPixmap(QtGui.QPixmap(":/my_pic/pic/lajiao.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
       self.pushButton.setIcon(icon1)
       self.pushButton.setObjectName("pushButton")
       self.pushButton_2 = QtWidgets.QPushButton(self.groupBox)
       self.pushButton_2.setGeometry(QtCore.QRect(20, 90, 151, 31))
       self.pushButton_2.setFixedHeight(40)  
       self.pushButton_2.setStyleSheet("QPushButton{color:white;background:Orange;border-radius:20px;border:3px solid black;}") 
       icon2 = QtGui.QIcon()
       icon2.addPixmap(QtGui.QPixmap(":/my_pic/pic/xiaoche.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
       self.pushButton_2.setIcon(icon2)
       self.pushButton_2.setObjectName("pushButton_2")
       self.groupBox_2 = QtWidgets.QGroupBox(self.centralWidget)
       self.groupBox_2.setGeometry(QtCore.QRect(240, 20, 671, 521))
       self.groupBox_2.setObjectName("groupBox_2")
       self.graphicsView = QtWidgets.QGraphicsView(self.groupBox_2)
       self.graphicsView.setGeometry(QtCore.QRect(10, 20, 651, 491))
       self.graphicsView.setStyleSheet("background-image: url(:/my_pic/pic/face.png);")
       self.graphicsView.setObjectName("graphicsView")
       self.line = QtWidgets.QFrame(self.centralWidget)
       self.line.setGeometry(QtCore.QRect(213, 20, 20, 521))
       self.line.setFrameShape(QtWidgets.QFrame.VLine)
       self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
       self.line.setObjectName("line")
       self.calendarWidget = QtWidgets.QCalendarWidget(self.centralWidget)
       self.calendarWidget.setGeometry(QtCore.QRect(20, 260, 201, 271))
       self.calendarWidget.setObjectName("calendarWidget")
       MainWindow.setCentralWidget(self.centralWidget)
       self.menuBar = QtWidgets.QMenuBar(MainWindow)
       self.menuBar.setGeometry(QtCore.QRect(0, 0, 930, 23))
       self.menuBar.setObjectName("menuBar")
       self.menu = QtWidgets.QMenu(self.menuBar)
       self.menu.setObjectName("menu")
       self.menu_2 = QtWidgets.QMenu(self.menuBar)
       self.menu_2.setObjectName("menu_2")
       self.menu_3 = QtWidgets.QMenu(self.menuBar)
       self.menu_3.setObjectName("menu_3")
       MainWindow.setMenuBar(self.menuBar)
       self.action = QtWidgets.QAction(MainWindow)
       icon3 = QtGui.QIcon()
       icon3.addPixmap(QtGui.QPixmap(":/my_pic/pic/open.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
       self.action.setIcon(icon3)
       self.action.setObjectName("action")
       self.action_2 = QtWidgets.QAction(MainWindow)
       icon4 = QtGui.QIcon()
       icon4.addPixmap(QtGui.QPixmap(":/my_pic/pic/close.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
       self.action_2.setIcon(icon4)
       self.action_2.setObjectName("action_2")
       self.action_3 = QtWidgets.QAction(MainWindow)
       icon5 = QtGui.QIcon()
       icon5.addPixmap(QtGui.QPixmap(":/my_pic/pic/connect.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
       self.action_3.setIcon(icon5)
       self.action_3.setObjectName("action_3")
       self.action_4 = QtWidgets.QAction(MainWindow)
       icon6 = QtGui.QIcon()
       icon6.addPixmap(QtGui.QPixmap(":/my_pic/pic/aboutme.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
       self.action_4.setIcon(icon6)
       self.action_4.setObjectName("action_4")
       self.action_QT = QtWidgets.QAction(MainWindow)
       icon7 = QtGui.QIcon()
       icon7.addPixmap(QtGui.QPixmap(":/my_pic/pic/aboutqt.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
       self.action_QT.setIcon(icon7)
       self.action_QT.setObjectName("action_QT")
       self.menu.addAction(self.action)
       self.menu.addAction(self.action_2)
       self.menu_2.addAction(self.action_3)
       self.menu_3.addAction(self.action_4)
       self.menu_3.addAction(self.action_QT)
       self.menuBar.addAction(self.menu.menuAction())
       self.menuBar.addAction(self.menu_2.menuAction())
       self.menuBar.addAction(self.menu_3.menuAction())

self.retranslateUi(MainWindow)
       QtCore.QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):
       _translate = QtCore.QCoreApplication.translate
       MainWindow.setWindowTitle(_translate("MainWindow", "波士顿房价预测系统 v1.0"))
       self.groupBox.setTitle(_translate("MainWindow", "房价预测操作"))
       self.pushButton.setText(_translate("MainWindow", "加载数据源"))
       self.pushButton_2.setText(_translate("MainWindow", "模型预测房价"))
       self.groupBox_2.setTitle(_translate("MainWindow", "模型预测结果"))
       self.menu.setTitle(_translate("MainWindow", "文件"))
       self.menu_2.setTitle(_translate("MainWindow", "帮助"))
       self.menu_3.setTitle(_translate("MainWindow", "关于"))
       self.action.setText(_translate("MainWindow", "打开"))
       self.action_2.setText(_translate("MainWindow", "关闭"))
       self.action_3.setText(_translate("MainWindow", "联系我们"))
       self.action_4.setText(_translate("MainWindow", "关于我们"))
       self.action_QT.setText(_translate("MainWindow", "关于QT"))

import my_pic_rc

if __name__ == "__main__":
   import sys
   app = QtWidgets.QApplication(sys.argv)
   MainWindow = QtWidgets.QMainWindow()
   ui = Ui_MainWindow()
   ui.setupUi(MainWindow)
   MainWindow.show()
   sys.exit(app.exec_())

信号与槽函数代码

class MainWindow(QMainWindow, Ui_MainWindow):
   """
   Class documentation goes here.
   """
   def __init__(self, parent=None):
       """
       Constructor
       
       @param parent reference to the parent widget
       @type QWidget
       """
       super(MainWindow, self).__init__(parent)
       self.setupUi(self)
       
   def model_plot(self, y_true,model_pre):
       '''
       y_true:真实的label
       model_pre: 预测的数据(数据框)
       '''
       cols = model_pre.columns
       plt.style.use("ggplot")
       plt.figure(figsize=(24,24))
       plt.rcParams['font.sans-serif'] = ['FangSong'] 
       plt.rcParams['axes.unicode_minus'] = False 
       for i in range(6):
           plt.subplot(2,3,i+1)
           plt.scatter(x=range(len(y_true)),y=y_true,label='true')
           plt.scatter(x=range(len(model_pre[cols[i]])),y=model_pre[cols[i]],label=cols[i])
           plt.title(str(cols[i])+':真实Label Vs 预测Label')
           plt.legend()
   
       plt.savefig("model_plot.png")
   
   @pyqtSlot()
   def on_pushButton_clicked(self):
       """
       Slot documentation goes here.
       """
       # TODO: not implemented yet
       print("加载数据")
       
       boston = datasets.load_boston()
       train = boston.data
       target = boston.target
       
       self.X_train,self.x_test,self.y_train,self.y_true = train_test_split(train,target,test_size=0.2)
   
   @pyqtSlot()
   def on_pushButton_2_clicked(self):
       """
       Slot documentation goes here.
       """
       # TODO: not implemented yet
       print("模型预测")
       
       # 模型加载
       lr_m = joblib.load("model/LR_model.m")
       rr_m = joblib.load("model/RR_model.m")
       llr_m = joblib.load("model/LLR_model.m")
       knnr_m = joblib.load("model/KNNR_model.m")
       dr_m = joblib.load("model/DR_model.m")
       svmr_m = joblib.load("model/SVMR_model.m")
       
       try:
           y_LR = lr_m.predict(self.x_test)
           y_RR = rr_m.predict(self.x_test)
           y_LLR = llr_m.predict(self.x_test)
           y_KNNR = knnr_m.predict(self.x_test)
           y_DR = dr_m.predict(self.x_test)
           y_SVMR = svmr_m.predict(self.x_test)
           
           
           model_pre = pd.DataFrame({'LinearRegression()':list(y_LR),'Ridge()':list(y_RR),'Lasso()':list(y_LLR), \
           'KNeighborsRegressor()':list(y_KNNR),'DecisionTreeRegressor()':list(y_DR),'SVR()':list(y_SVMR)})
           
           self.model_plot(self.y_true, model_pre)
           self.graphicsView.setStyleSheet("border-image: url(model_plot.png);")

except:
           my_button_w3=QMessageBox.warning(self,"严重警告", '请务必先加载数据然后再点击模型预测!!!', QMessageBox.Ok|QMessageBox.Cancel,  QMessageBox.Ok)

@pyqtSlot()
   def on_action_triggered(self):
       """
       Slot documentation goes here.
       """
       # TODO: not implemented yet
       print('打开')
       my_button_open = QMessageBox.about(self, '打开', '点击我打开某些文件')
   
   @pyqtSlot()
   def on_action_2_triggered(self):
       """
       Slot documentation goes here.
       """
       # TODO: not implemented yet
       print('关闭')
       sys.exit(0)
   
   @pyqtSlot()
   def on_action_3_triggered(self):
       """
       Slot documentation goes here.
       """
       # TODO: not implemented yet
       print('联系我们')
       my_button_con_me = QMessageBox.about(self, '联系我们', '这个位置放的是联系我们的介绍')
   
   @pyqtSlot()
   def on_action_4_triggered(self):
       """
       Slot documentation goes here.
       """
       # TODO: not implemented yet
       print('关于我们')
       my_button_about_me = QMessageBox.about(self, '关于我们', '这个位置放的是关于我们的介绍')
       
   
   @pyqtSlot()
   def on_action_QT_triggered(self):
       """
       Slot documentation goes here.
       """
       # TODO: not implemented yet
       print('关于qt')
       my_button_about_QT = QMessageBox.aboutQt(self, '关于QT')

if __name__ == "__main__":
   import sys
   app = QtWidgets.QApplication(sys.argv)
   splash = QSplashScreen(QtGui.QPixmap(':/my_pic/pic/face.png'))
   splash.show()
   QThread.sleep(0.5)
   splash.showMessage('正在加载机器学习算法...' )
   QThread.sleep(1)
   splash.showMessage('正在初始化程序...')
   QThread.sleep(0.5)
   #splash.show()
   app. processEvents()
   ui =MainWindow()
   # ui.setDaemon(True`)
   # ui.start()
   ui.show()
   splash.finish(ui)
   sys.exit(app.exec_())

4.打包成exe可执行文件

上面代码运行通过后,我们的基本任务也已经完成,但是业务人员仍然不可用,我们可以生成exe可执行文件,把运行环境所需要的dll文件打包,这样业务人员就可以脱离Python环境进行算法的使用了。 Python中打包成exe可执行文件的方式有很多种,这里我们使用pyinstaller来打包成可执行文件,打包命令为:

pyinstaller my_main_ui.spec

OK,我们打包成功后就可以运行了,运行结果如下,我们生成的工具放在了百度云盘,可以在百度云盘下载测试(注意:生成的版本是win7 64位的版本

5.小结

这样我们就完成我们的小项目了,当然Pyqt的很多控件和方法我们都没有讲到,如果你对Python GUI的开发感兴趣,可以详细的玩一下Pyqt的其他控件,做出一个高大上的应用。本文中提到的所有源码我都放在了我的Github上,欢迎小伙伴们fork和留下star,同时也欢迎小伙伴留下自己的issues,源码托管地址:https://github.com/DataXujing/boston_model

原文发布时间为:2018-09-5

本文作者:徐静

本文来自云栖社区合作伙伴“Python爱好者社区”,了解相关信息可以关注“Python爱好者社区”。

【好文】带你用Python开发个机器学习软件!相关推荐

  1. python中集合运算_入门 | 一文带你了解Python集合与基本的集合运算

    原标题:入门 | 一文带你了解Python集合与基本的集合运算 选自DataCamp 作者:Michael Galarnyk 参与:Geek Ai.思源 一般我们熟悉 Python 中列表.元组及字典 ...

  2. Python开发多媒体管理软件实现方法

    软件开发环境 python 3.7.3 pycharm Community 2020 PYQT5 教师端控制界面 下拉列表显示全部已经连接的客户端ip地址 对选中的设备进行查看设备信息,重启电脑,关闭 ...

  3. 做python项目需要知道什么_一文带你了解python是什么?能做什么?为什么要学?(文末附学习资源)...

    什么是 Python? Python 是一门流行的编程语言.它由 Guido van Rossum 创建,于 1991 年发布. 它用于:1.Web 开发(服务器端) 2.软件开发 3.数学 4.系统 ...

  4. python开发的著名软件公司_软件开发公司_软件外包_项目外包平台基于Python开发一个全文检索系统...

    基于Python开发一个全文检索系统.功能要求为: 使用全文检索引擎对文本进行检索.文本的格式为Word.PDF.TXT. 同时按数据域进行复合条件检索.数据域指文本对应的信息,例如创建人.文件编号. ...

  5. 带你入门Python数据挖掘与机器学习(附代码、实例)

    作者:韦玮 来源:Python爱好者社区 本文共7800字,建议阅读10+分钟. 本文结合代码实例待你上手python数据挖掘和机器学习技术. 本文包含了五个知识点: 1. 数据挖掘与机器学习技术简介 ...

  6. python开发app的软件_如何利用python开发手机app

    python语言虽然很万能,但用它来开发app还是显得有点不对路,因此用python开发的app应当是作为编码练习,加上目前这方面的模块还不是特别成熟,bug比较多. 准备工作 利用python开发a ...

  7. 一文带你用python做自动化测试

    python 是目前测试推广最多的语言,翻翻各大招聘公司,测试要求会 python的比比皆是,而且易学易用. Selenium 是 Thought Works 公司开创的一套基于 web 应用的自动化 ...

  8. python主要用于系统编程_一文带你了解python是什么?能做什么?为什么(附赠40G项目实战+绝版电子书)...

    什么是 Python? Python 是一门流行的编程语言.它由 Guido van Rossum 创建,于 1991 年发布. 它用于:当然小编这里也准备一份适合你的学习资料爬虫 ,python学习 ...

  9. 谈谈你了解的python_你也可以侃侃而谈,一文带你了解Python的前世今生

    那是1989年的事情了,Python是由Guido van Rossum在这年年底出于某种娱乐目的开发的,Python语言是基于ABC教学语言的,ABC语言大家应该清楚,是专门为非专业程序猿设计开发的 ...

最新文章

  1. 吐槽一下微信公众号的赞赏号
  2. 【OpenCV3】棋盘格角点检测与绘制——cv::findChessboardCorners()与cv::drawChessboardCorners()详解
  3. NLP之WE之Skip-Gram:基于TF利用Skip-Gram模型实现词嵌入并进行可视化、过程全记录
  4. k8s pod的创建流程图示
  5. python判断点在直线的哪一侧_判断点在直线的哪一侧
  6. Java编程规约(OOP)
  7. mysql查看版本号_十分钟了解MySQL事务机制
  8. 使用MOE进行药效团建模与分析
  9. 计算机打开管理工具空白,大师解决win10系统打开设备管理器却显示空白的办法...
  10. 《软技能—代码之外的生存指南》
  11. vector 内部方法大全 学习(初学者的参考资料)
  12. querySelector() 选择器语法
  13. 给龙芯的OpenJDK8升级
  14. vba正则表达式入门
  15. 使用IDEA搭建SSM项目
  16. 独孤求败,未必就是王者:CloudStack和Eucalyptus已去,OpenStack赢了吗?
  17. datatables rows selected
  18. HTML+CSS练习——实现京东登录静态页面
  19. [线段树][数学] Jzoj P4237 Melancholy
  20. 分数阶 计算机应用,分数阶计算器

热门文章

  1. sizeof用法研究
  2. MySQL-Front,MySQL的企业管理器
  3. 十一:外观模式详解(Service,action与dao)
  4. Vue---自定义组件
  5. docker一:mac入门安装
  6. gedit emacs
  7. 浅谈likely与unlikely
  8. vbscript调用WMI一键式式发布网站
  9. JS三大对象中常用方法集锦
  10. 资源2010-01-29