软件工程论文

您当前的位置:学术堂 > 计算机论文 > 软件工程论文 >

智能家居数据管理模块

来源:学术堂 作者:姚老师
发布于:2017-02-07 共5607字
  本篇论文快速导航:

展开更多

  第 4 章 基于机器学习的智能家居系统

  4.1 系统总体架构。

  4.1.1 模块化设计。

  一个系统的架构非常重要,作为与生活十分贴近的智能家居系统,系统运行的灵活性,稳定性,适应性等一系列特性都是至关重要的,所以基于机器学习的智能家居系统总体架构必须考虑到各个方面,把系统中各个方面尽量好地与智能家居对接明确,并通过模块化的设计[28],使得系统中的各个功能相对独立,目的明确,界限清晰,各个模块完成各自模块所设计的任务,在出问题时也不会影响到其它模块,实现各个模块之间,整个系统内部的数据共享,互相协作完成整个任务,展现出系统的稳定性,灵活性和鲁棒性。

  模块化设计指的是将系统中功能相似的要素组合到一起,形成一个功能类似,目的专一的模块,再为这个模块提供需求的接口,与其它模块进行结合,形成一个整体的系统。考虑到使用模块化设计可以缩短系统开发周期,快速应对出现的各种需要变化,也方便对模块的重用,升级,还有后续的维护,所以本文所设计的基于机器学习的智能家居系统也采用了模块化设计。

  使用模块化设计可以让系统灵活性大大地增加,所以现在模块化设计也已经成了系统设计的一个趋势,使用模块化设计还可以有如下几个优势:

  1. 相对独立性,由于每个模块独立设计,所以可以单独对模块进行设计,实现,调试和修改。

  2. 互换性,模块化设计可以提供一个标准化的接口,其它模块只要对接接口即可,不需要考虑模块的具体实现,因此很容易实现不同功能模块之间的互换,满足不同需求的出现。

  3. 通用性,上层的模块不需要考虑低层的实现,因此仅需要设计低层模块,就可以把模块用到各个不同的系统中。

  考虑到模块化设计的优势,这对于现在还处于高速发展的智能家居系统来说,是一个非常有价值的特点,模块化使得分工合作变得容易,可以加速系统的开发速度,而随着新技术的出现,系统肯定需要考虑更新自身不足以完善系统,模块化也使得系统可以在必要时放弃过时的模块,而使用全新的模块更换原模块。

  结合以上分析,本文所设计的系统按照数据流的方向,把整个系统细分为以下几个模块:

  1. 任务管理模块,完成机器学习系统中对各个任务的调度2. 数据管理模块,完成机器学习系统中与数据库对接,并返回所读取数据3. 预测模块,机器学习的核心模块,完成各节点的训练与预测4. 网络通信模块,完成机器学习部分与原有智能家居的对接。

  系统各模块之间的关系。

  首先系统先从服务器中读取所有节点的列表,并根据节点列表进行任务管理,任务在各个模块中执行过程都是通过接口与任务管理模块进行交互,各个模块需要做的就是完成自身的任务,并提供接口供任务管理模块调用。

  对于智能家居系统而言,机器学习系统运行于智能家居服务器上,考虑到可移植性,我们依旧使用网络接口与智能家居服务器进行通信,通过 UDP 协议向智能家居服务器请求节点数据与发送预测结果。另一方面,对于数据库,我们使用了数据管理模块,可以根据实际情况直接读取数据库数据或者通过网络接入数据库,进行数据读取。机器学习系统在智能家居系统内的整体结构。

  4.1.2 系统特性。

  上文中提到基于机器学习的智能家居系统设计中,必须考虑到的一点就是节点的灵活性。作为智能家居系统,用户出现新加入设备,删除设备,或者更换设备,都是会经常出现的情况,所以系统必须把灵活性作为首要考虑点。在本文所设计系统中,每一个机器学习任务都是基于每一个节点进行的,所以无论是节点发什么各种改变,机器学习系统都可以对智能家居系统的变化做出反应,及时地增加或减少节点任务。

  机器学习系统通过以节点为单位进行机器学习,增加了系统的灵活性,但同时也必须得考虑智能家居系统的整体性,智能家居作为一个家庭整体,在家中的设备有着非常强的关联性,只有将所有智能家居设备状态组合成一个整体,才能实现整个家居的感觉,这也是为什么现在所有公司都在追求能够推出一系列智能家居产品,同时构建自己的生态链。只有所有设备能够互联,互通,互相协作才能实现智能家居的整个生态系统和其智能化。所以在任务节点化之余,本文系统设计在训练神经网络模型读取系统数据时,每次都会读取所有的数据,包括各种传感器数据与各个设备的当前状态,并把设备的历史状态作为训练数据输入,通过将整个智能家居系统的节点数据作为整体输入,系统在训练神经网络时,会结合整个系统,强调节点与整个系统状态之间的关系。

  同时,在进行预测时,系统也会读取智能家居系统最新的传感器和设备状态信息,然后通过本节点所训练得到的人工神经网络进行预测,当系统状态发生改变时,与变化相关部分的节点的最新预测结果也会随着系统变化而变化,当多个节点都进行了预测得到新的状态后,整个系统就会进行一个新的情景模式,由此,我们的机器学习系统可以拥有变换情景模式的能力。

  有了以上的分析,下面我们可以说明系统中的各个模块设计和实现。

  4.1.3 实现平台。

  本文系统主要使用 TensorFlow 作为主要机器学习系统完成实现工作,所以围绕 TensorFlow 进行开发平台选择。

  首先 TensorFlow 官方支持的语言有 C++和 Python,考虑到基于机器学习的智能家居系统现在处于一个研究与实现相过度的快速发展阶段,如果有新技术出现而且可以解决一些关键问题,系统必须有能力快速切换到新技术上,所以快速开发是一个重要的要求。最好就是能够以较小幅度的规划并迅速地将原型完成并在此之上完成新版本的不断更新迭代,也就是通常所说的快速应用程序开发方法论。

  C++是最流行的开发语言之一,也是公认的最强大的语言之一,使用 C++可以设计静态类型,开发出性能十分优秀的可移植应用程序,但是其最大的问题就是其语言本身过于复杂,导致开发难度相对较大,也因为 C++使用了一些相对低层的调用,所以虽然 C++开发的程序有可移植性,但是却不易移植。因此 C++适合开发性能要求高的应用程序,但是在此却不一定合适。

  Python 是一个面向对象的解释式语言,最突出的特点就是其语法简单,并且其标准库与第三方库的功能十分强大和完善,使用 Python 可以很轻松地编写一些复杂的程序。Python 虚拟机可以在常见的操作系统中运行,这也使得 Python具有非常良好的可移植性,甚至可以使用 PyPy 将 Python 程序转换为可以直接在机器上运行的程序。在 Python 无法满足性能需求时,还可以使用 C 语言编写一些性能要求高的函数,再使用 Python 调用该函数,从而达到提高性能的目的。

  由于以上特性,使用 Python 可以非常好地满足快速开发要求,同时可也可以满足性能要求,还有着跨平台的优势。

  综上所述,使用 Python 作为开发语言是一个合理的选择,而 Python 带来的跨平台优势使得我们可以不用过多在意运行平台,在测试中我们使用的是 MacOS X 10.11,是一个基于 Unix 的操作系统。

  4.2 任务管理模块。

  任务管理模块是基于机器学习的智能家居系统的中心模块之一,任务管理模块通过调用各个模块的接口衔接了其它各个模块,调度了整个系统的任务运行。

  4.2.1 并发性处理。

  由于系统以各个设备为单元进行训练和预测,每次在进行训练与预测时,都会产生大量的任务,顺序完成这些任务必定会导致一次系统运行时间过长,造成大量的任务堵塞。另外机器学习系统要从数据库中读取数据,并通过网络与服务器进行交互,因此也会有大量的磁盘 IO 和网络 IO,这些 IO 时间也造成了大量的时间浪费,所以任务管理模块必须提高系统的并行性[29].

  Python 语言的简单使得编写 Python 程序时难度降低入许多,但是在并发方面,却一直是 Python 的一个软肋,这是由于官方的 Python 实现是 CPython,这也是最通用的一个 Python 实现,但是它并不是线程安全的,所以 Python 使用了一个全局解释锁来处理线程安全的问题,这也直接导致 Python 没有办法真正地多线程运行。Python 程序运行时,只有唯一的一个线程能够获取 Python 对象,这个全局解释锁的存在会阻塞 IO 操作,所以常常发现在使用了多线程时,程序的运行效率反而下降了。

  但是这并不说明 Python 的并发问题无法解决在 Python 的第三方库中,有一个叫 Gevent 的协程并发框架,可以很好地提高 Python 程序的并发性。

  Gevent[30]是一个基于协程的 Python 网络库,其主要理念是快速事件循环,事件循环在 Linux 的实现是 epoll,FreeBSD 上是 kqueue,在出现耗时任务时,Python会自动地切换到另一个任务中,直到耗时任务完成之后,再返回原任务中,这样就可以使得程序不会把时间浪费在空等待中,能够充分利用计算机的运行能力。

  通过事件循环理念,Gevent 为 Python 提供了一个名为 greenlet 的轻量级执行单元,使得 Python 也拥有了多线程能力。

  Gevent 只是 Python 实现并发的其中一种方式,Python 也有其它方式实现并发。

  Python 主要官方就带有一个线程库,threading,这个线程库也是利用了Python 语言中使用 IO 的时间占用比 CPU 占用长,所以在 IO 时可以运行另一个线程,threading 线程库可以为每个要 IO 的数据项产生一个线程去访问数据。

  Gevent的实现与threading的原理基本类似,而且Gevent在使用过程中比threading更强大方便,所以使用 Gevent 更能满足我们的需求。

  另一个著名的库是多进程处理库 Multiprocessing,这个多进程处理库真正地使用到了操作系统的多个处理核心,其为每个子进程赋予单独的 Python 解释器和单独的全局解释锁(GIL),使得程序可以同时在多个核心上运行而不受 GIL影 响,在所 有 子进程运行结 束后再对所有进程进行一个重组。看似Multiprocessing 库解决了并发的问题,但是实际使用过程中,多个子进程的数据交换带来了另外的 IO 问题,容易引起程序本身的数据混乱,反而使得程序效率下降。而本文的系统数据会有许多交互,而且在使用 TensorFlow 时,会自动地调用机器的各个处理核心,所以 Multiprocessing 库在此也不是最好的选择。

  综上所述,本系统采用了 Gevent 解决并发性的问题,Gevent 库可以为系统带来效果很好的并发性,同时也不会带来额外的副作用。

  4.2.2 优先级处理。

  通过使用 Gevent,我们大大提高了程序的并发度,同时考虑到在智能家居中,有一些设备对实时性要要求是比较高的,必须要时刻关注着设备的状态,就像运行中的插座,安保等相关设备,燃气设备等,对于这样的设备,必须积极地处理其状态,以及时地发现有危险或者紧急事故出现;有一些设备对时间的要求不那么严格,如客厅的窗帘,灯等,我们只需要定期,隔一段不那么长的时间处理其状态即可。因此,我们可以把设备按照对实时性需求分多个优先级,并且在对设备进行预测时,根据优先级的高低先后处理各设备的预测。

  根据节点优先级,我们设置相应优先级队列。在读取节点列表之后,高优先级的设备与低优先级设备分别进入相应优先级队列,低优先级队列每五分钟重复一次轮询节点状态,高优先级队列三十秒钟重复一次轮询节点状态,在执行过程中,不同优先级之间的设备除了数据共享以外并不互相影响。

  通过为优先级队列设置不同的轮询间隔时间,达到了优先处理高优先级设备的效果。

  4.3 数据管理模块。

  数据管理模块为系统提供读取数据的功能,通过为系统提供名为 read_data的接口函数,返回训练集中的 x 和 y 值以供训练和预测。

  4.3.1 数据接口。

  数据管理模块所提供的接口是 read_data 函数,对于系统来说,只有接口是可见的,数据的具体读取过程是透明的,模块仅需要为系统提供系统需要的数据即可。其中系统需要提供三个参数:

  1. 路径,数据具体存放的位置,模块可以按照路径找到目标。

  2. 样本数,每次训练需要的样本数,模块每次仅返回要求的样本数,以节省内存。

  3. 类型标志,读取数据时,根据数据的不同用途,有三类数据用于训练,还有一类数据用于预测,所以一共有四类数据,模块必须按照标志返回相应数据。

  在第三个参数中提到了有四类数据,所以我们必须使用一个标志来判断数据类型,得益于 Python 的对象机制,我们可以很轻易地完成字符串之间的比较,所以在此标志我们可以直接使用字符串类型表示,分别有:

  1. predict,表示返回预测数据,标志为此时不考虑样本数参数,直接返回最新数据,以供预测使用。

  2. train,表示返回一个训练集数据,训练集大小由样本数参数指定。

  3. validation,表示返回一个交叉验证集,交叉验证集大小由样本数参数指定。

  4. test,返回一个测试集,测试集大小由样本数参数指定。

  除了以上四类数据,考虑到有可能会出现仅希望得到部分数据的情况出现,所以在标志无法匹配时,在整个数据库中返回部分数据。而上文也分析过,在返回数据时,必须使用乱序数据,以减少数据之间的相关性,所以除了返回预测数据仅返回一条数据,其余在返回数据时,都是从大数据集中随机返回一定量的样本。

  4.3.2 具体实现。

  在研究阶段,本文从哈佛大学数据分享平台中找到了一个 2010 年间智能家居数据分享,在对数据进行简单处理后,可用于本文的研究。

  得益于模块化的特性,针对不同数据,我们仅需要修改对应的数据模块即可完成对系统的更新,所以使用该数据并不会对本文系统的应用造成过多问题。

  实验数据根据类型的不同放在不同的文件中,数据管理模块依次从各个文件中读取各类数据的数据,并按照不同的设备将数据保存到程序列表中,利用Python 提供的 yield 和 generator 生成器,我们可以为每个数据集生成一个generator 生成器,然后通过使用 yield 每次从生成器中读取想要的数据,这样可以在需要读取数据时,仅读取需要部分,而不需要每次都读取全部数据,浪费内存使用。

  生成器指的是一个使用 yield 返回,而不是 return 的函数,该函数在运行时会记住上一次运行到的函数位置,再次调用生成器时,函数会直接从上次运行的位置开始执行,并且保持上一次调用的相关局部变量不变,直到函数完成执行完毕,生成器结束。通过生成器的使用,我们可以很好地节约内存的使用,而且可以使用多个不同的生成器用于表示不同的数据集,使代码更清晰。生成器的使用在数据量大的一定程序时,会表现出比常规写法优秀许多的效率。

  通过设计返回相应数据集的生成器,数据管理模块也就完成了其任务。

返回本篇论文导航
相关内容推荐
相关标签:
返回:软件工程论文