/
search.xml
77 lines (53 loc) · 27.1 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[直播项目阶段性总结-爬虫]]></title>
<url>%2F2017%2F02%2F19%2Flivetv-mining-summary-spider%2F</url>
<content type="text"><![CDATA[爬虫总结项目展示的数据都是由爬虫爬取的,在使用过程中出现了很多没有注意和意料之外的一些问题,特此总结一下提醒自己。 历程爬虫开发的技术路线经过了好几个阶段,将一一总结: 原生写法urllib Requests + Gevent + Celery Scrapy + Redis 原生写法urllib这个阶段是刚开始学习爬虫,对如何构造和理解爬虫以及相关库的用法都不熟悉,是学习踩坑阶段。主要学习了响应的解析和处理,XPath和正则提取数据。还探索性使用自动化测试组件Selenium,调用浏览器直接爬取数据,用以对付一些反爬虫策略复杂的网站。在对爬虫有了基础的了解以后,开始准备在生产环境使用。爬虫根据站点变化经常需要调整,也需要定时任务定期执行,为了适应这种情况进行一次技术升级。 主要缺点:结构不清晰,写法繁琐。修改爬虫的时候不方便,模块化程度不高。 Requests + Gevent + Celery此阶段完成开发主要为: 模块化。 爬虫定时启动管理。 提高爬取效率,初步反爬虫策略。 针对每点都做了以下工作: 重新设计,开发了爬虫基类,包含启动和队列函数。子类继承后,只需要补全格式化数据和存储部分即可。采用requests替代python标准库,提升开发效率。 采用Celery作为爬虫任务管理,定时启动爬虫、超时删除等,并开发Flask-Celery(py3版本)插件。 从试验结果看来,爬虫运行时间主要浪费在I/O读写(网络通信)上,还占用&浪费CPU工作时间。故引入了协程Gevent,在I/O读写时CPU可以继续其他数据的分析和存储任务,总体上缩短爬虫运行时间。采用的初步的反爬虫措施,设置user-agent,随机间隔几秒启动对站点的访问请求。 配合WEB展示部分,直播爬虫站点在这个时期上线了,达到了自行更新直播房间的情况。但仍然存在以下的问题: 模块化仍然有优化的需要,仅能先频道后房间的方式爬取。 爬虫一旦超时或发生错误,Celery只能重新启动爬虫任务,无法在某个特定频道/房间请求上重试。 由于生产环境机器性能不足(AWS免费套餐),导致爬虫进程在运行占用CPU的时候,展示WEB站点的请求几乎得不到正确的响应。 这些问题都影响到项目正常运行,所以还是进行技术升级修正。恰逢此时,爬虫包scrapy终于完成了对py3的兼容,研究后认为它的框架设计基本上能解决我遇到的问题,而且更灵活,配置和修改爬虫都非常方便。故采用Scrapy进行升级替换。 Scrapy + RedisScrapy的基本模块和运行方式可以参照下图: 按运行顺序说明: Spider(请求构造工厂):开发人员自定义的爬虫请求Request、数据分析以及构造Item。构造后的爬虫请求Request进入Scheduler,Item进入Pipeline。 Scheduler(调度程序):接收到构造好的爬虫请求后安排队列,按队列先进先出方式提供请求给Downloader。默认队列为multiprocess.queue,此处我采用了redis替换,这样当进程意外终止甚至机器重启的情况下仍可以恢复爬虫继续。 Downloader(下载器):接收到请求Request后访问站点,将得到的响应返还给Spider。此处引入了user-agent替换插件,可根据已存在user-agent文本随机替换请求相应值。 Pipeline(管道):在Spider初步处理得到Item,Item会被发送到Pipeline进一步处理,并且多个Spider可以生成相同格式的Item交给Pipeline统一处理。Item流动经过的Pipeline顺序通过weight(权重)设置。 以上均由Engine操作执行。 Scrapy采用Twisted实行多爬虫异步爬取,Twisted的异步进程处理非常强大,在等待I/O过程中会释放占用的CPU,这样多个爬虫即使在单CPU的情况下仍然能高效的切换进行。 可以说Scrapy解决了我所有的项目痛点,在生产环境中的表现也很好,目前运行稳定。 不采用PySpider理由PySpider研究后就我理解来说,它更像是一揽子完备的解决方案,自由度低。Scrapy相对只是个第三方库,使用的方式更自由,且插件丰富,自己定制开发也方便,更适合个人项目。 阶段总结目前Scrapy已经很好胜任了我的爬虫任务需要,接下来的爬虫功能追加将会在弹幕读取上下功夫。如果Scrapy无法满足需要,优先开发Scrapy自定义插件,实在不行才考虑替换Scrapy。]]></content>
</entry>
<entry>
<title><![CDATA[webpack配置使用]]></title>
<url>%2F2017%2F01%2F21%2Fwebpack-config%2F</url>
<content type="text"><![CDATA[webpack打包单页前端项目 在项目 直播爬虫 的前端开发过程中,使用了webpack集成打包,实现了单页面前端的效果。特写此文总结webpack使用经验与配置。 webpack特点 webpack对于各种主流模块的安装依赖、不同规范语法(amd/cmd/commonjs),以及不同的模块加载器和插件等都有很好的支持,开发人员可以通过配置轻松打包一个项目,减少学习成本。或者换句话说,对于我这样前端开发接触不多的开发者,webpack提供了一整套方便处理的编译打包测试方案。 一切资源都可以模块化的工作方式,也很符合后端开发者一贯思维方式。同时还提供了丰富的插件供选择,基本上可以满足前端开发需求。 上面提到的都是webpack优势,现在来说说它的不足。首先webpack项目事件不是很长,目前1.x稳定版2.x开发版,我稍微看了下内容担心会像angular一样会有跨度大,迁移学习成本高的问题。第二点webpack本身配置和使用文档内容很繁琐,且质量不高,更别提其他的第三方插件了,我使用下来感觉不是很顺畅,初期学习成本比较陡峭。 与其他几种主流打包比较,建议看下这篇文章 Module loader comparison。 反正我自己是在用了webpack后把gulp全删了,懒! 配置介绍(持续更新) 以直播项目配置为例,介绍如何配置webpack。官网 目前分为三个文件:base(基础),dev(开发),prod(生产)。 dev与prod的区别主要是在plugins上: dev中包含了热启动和webpack-dev-server启动的信息。 webpack.optimize.OccurrenceOrderPlugin() webpack.HotModuleReplacementPlugin() webpack.NoErrorsPlugin() prod包含了混淆css、js文件,以及html文件压缩处理。 webpack.optimize.UglifyJsPlugin({compress: {warnings: false}})]]></content>
</entry>
<entry>
<title><![CDATA[Vue.js前端项目总结]]></title>
<url>%2F2017%2F01%2F11%2Fvue-project%2F</url>
<content type="text"><![CDATA[历程 近期完成了个人站点 直播爬虫 的前后端分离的改造,使用 vue+vue-router+vuex 的方式来构建项目。分离过程中对规划组建前端项目有一点自己的心得体会。 工具 采用npm+webpack编译打包项目。webpack配置文件可参考例子。 项目结构 以下为个人总结的项目结构,详细可查看github。 文件夹src内容解释: components 公共组件,通用页面/功能存放。 filters 公共过滤器,通用过滤方法存放。 resource RESTFul资源,目前采用vue-resource管理资源。 router 路由创建,由vue-router管理。 store 全局持久数据存储,由vuex管理。 views 页面组件,访问页面存放处,资源的调用仅能在此目录下的组件中进行。 App.vue 根vue模块。 main.js webpack打包根js脚本。 这样划分后基本涵盖了前端项目开发中涉及到的内容。 开发规范/经验(持续更新) 一些开发过程中个人遵循的规范和经验,可以比较好提升工作效率。 公共组件不包含资源调用,数据仅由外部组件传入。 在两个以上页面组件中出现重复html代码,该html代码必须拆分为公共组件。 页面组件不得使用ajax获取数据,只能使用resource获取。 页面组件获取数据只能与store交互,再通过store传递到其他页面组件。 访问权限控制,通过路由 meta: { auth: … } 管理。 用户登录的场景,当用户登录后,store保存用户信息,router在每次切换时要验证session是否有效。若无效,删除store中用户信息。]]></content>
</entry>
<entry>
<title><![CDATA[随机拆分一个正数为任意份]]></title>
<url>%2F2016%2F12%2F24%2Fsplit-one-integer-to-serveral%2F</url>
<content type="text"><![CDATA[问题提出设一个正数sum,需将其随机分为n份,其和仍保持为sum。 思路思考线索如下: 先转为正整数问题,浮点数可以转为整数*10^m(m<0) 替换处理。 问题转变:假设存在sum个点排为一列,则存在sum-1个间隔。往间隔中插入n-1个分割板,将点分为n份。 解决步骤:随机抽取n-1个小于sum的数组成数组,进行顺序排序,并在头部加0,尾部加sum。每个数之间的差(分割板位置)即可得到相加为sum的n份数据。 如果为浮点数需要复原。 代码(Python)12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152# !/usr/env/bin python# -*- coding: utf-8 -*-from decimal import Decimalimport randomdef split_integer(prototype, part): if not (isinstance(prototype, int) and isinstance(part, int)): raise ValueError('Input params should be integer.') if part <= 1: raise ValueError('Split part should be more than 1.') if prototype <= part: raise ValueError('Split part should be more than split prototype.') board_set = set() while len(board_set) < part - 1: board_set.add(random.randrange(1, prototype)) board_list = list(board_set) board_list.append(0) board_list.append(prototype) board_list.sort() return [board_list[i + 1] - board_list[i] for i in range(part)]def split_float(prototype, part): if not isinstance(prototype, float): raise ValueError('Input prototype should be float.') if not isinstance(part, int): raise ValueError('Input part should be integer.') prototype = Decimal(str(prototype)) _, decimal_digits, decimal_exponent = prototype.as_tuple() union_int = Decimal('0') pow_base = Decimal('10') for i, d in enumerate(decimal_digits): union_int += Decimal(str(d)) * pow_base ** (len(decimal_digits) - 1 - i) return [float(v * pow_base ** decimal_exponent) for v in split_integer(int(union_int), part)]if __name__ == '__main__': ''' integer sample ''' part = random.randrange(2, 10) sample_int = random.randrange(20, 100) print(part, sample_int) res_int = split_integer(sample_int, part) print(res_int) ''' float sample ''' part = random.randrange(2, 10) sample_float = round(random.uniform(20, 100), 8) print(part, sample_float) res_float = split_float(sample_float, part) print(res_float)]]></content>
</entry>
<entry>
<title><![CDATA[海量数据中快速找到最大的100个]]></title>
<url>%2F2016%2F12%2F14%2F100-hundreds-million-number%2F</url>
<content type="text"><![CDATA[问题提出存在五十万个数字,如何快速找到最大(小)的100个。 思路思考线索如下: 普通排序方式,需要同时把数据全部加载到内存排序,由于python性能问题不采用。 采用堆排序(heapq)的方式提升排序速度。 不全部加载,每次取500个数据,取其中最大100个。然后再以每次500个加载比较。 代码(Python)123456789101112# !/usr/env/bin python# -*- coding: utf-8 -*-import heapqimport randomif __name__ == '__main__': sample = [] for _ in range(1000): sample += [random.randint(1, 100000) for _ in range(500)] sample = heapq.nlargest(100, sample) print(sample)]]></content>
</entry>
<entry>
<title><![CDATA[快速查找两个数组中相同浮点数]]></title>
<url>%2F2016%2F12%2F09%2Ftwo-array-compare%2F</url>
<content type="text"><![CDATA[问题提出存在两个浮点数数组A、B,如何能快速查找到: 浮点数x在数组A、B中都存在。(1:1) 数组A存在浮点数y,与数组B中浮点数y1、y2….yn相加值相等。同样也在数组B中作相同查找。(1:N or N:1) 数据特征数组的情况和解决方式要求为: 数组长度不会超过10000,但也不会低于1000。 两数组长度不等。 80%-90%的浮点数是符合1:1的情况。剩下的浮点数中都为1:N组合。 查找时间控制在1s内。 思路思考线索如下: 是否存在通用方法解决三种查找情况?不存在,由全组合公式可知存在的组合数量:2的N次方-1(N为数组长度)。由于数组长度不可采用此方式。 按照先后顺序过滤?先查1:1,再查1:N。 1:1怎么查?循环查找不可取,浮点数先对数组正序排序,再按照数组顺序查找相同元素。 1:N怎么查?过滤完1:1元素,数组仍然是正序排列。按顺序选取数组A中元素a,查找数组B中所有小于a的浮点数族为数组b,对b进行全组合后相加,得到结果与a比较。对数组B也采取相同方式。 代码(Python)123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157# !/usr/env/bin python# -*- coding: utf-8 -*-from collections import dequeimport itertoolsdef find_one_to_one(portalA, portalB): if len(portalA) <= 0 or len(portalB) <= 0: return None, portalA, portalB OneToOne, A_filter, B_filter = [], [], [] A = deque(sorted(portalA)) B = deque(sorted(portalB)) while len(A) > 0 and len(B) > 0: if A[0] == B[0]: OneToOne.append(A[0]) A.popleft() B.popleft() elif A[0] < B[0]: A_filter.append(A[0]) A.popleft() else: B_filter.append(B[0]) B.popleft() else: if len(A) > 0: A_filter.extend(A) if len(B) > 0: B_filter.extend(B) return OneToOne, A_filter, B_filterdef match_selected_number(comb_index_list, one_object, many_array): if len(comb_index_list) > 0: comb_max_size = len(comb_index_list) while sum(comb_index_list[:comb_max_size]) > one_object: comb_max_size -= 1 else: if comb_max_size < 2: return False, None for comb_size in range(2, comb_max_size + 1): for comb_tuple in itertools.combinations(comb_index_list, comb_size): if abs(one_object - sum([many_array[comb_index] for comb_index in comb_tuple])) <= 1: many_comb = [] many_last_split_index = 0 many_split = [] for temp_index in comb_tuple: many_comb.append(many_array[temp_index]) many_split += many_array[many_last_split_index:temp_index] many_last_split_index = temp_index + 1 else: many_split += many_array[many_last_split_index:] return True, (many_comb, many_split) return False, Nonedef find_one_to_many(portalA, portalB): if len(portalA) <= 0 or len(portalB) <= 0: return None, portalA, portalB OneToMany = [] A = sorted(portalA) B = sorted(portalB) comb_index_list = [] tag = 'A' A_index, B_index = 0, 0 while A_index < len(A) and B_index < len(B): if A[A_index] < B[B_index]: if tag == 'A': comb_index_list.append(A_index) A_index += 1 else: tag = 'A' res_bool, res_tuple = match_selected_number(comb_index_list, A[A_index], B) if res_bool: OneToMany.append((A[A_index], res_tuple[0])) A.remove(A[A_index]) B = res_tuple[1] comb_index_list = [] A_index, B_index = 0, 0 else: comb_index_list = list(range(0, A_index + 1)) elif A[A_index] > B[B_index]: if tag == 'B': comb_index_list.append(B_index) B_index += 1 else: tag = 'B' res_bool, res_tuple = match_selected_number(comb_index_list, B[B_index], A) if res_bool: OneToMany.append((B[B_index], res_tuple[0])) B.remove(B[B_index]) A = res_tuple[1] comb_index_list = [] A_index, B_index = 0, 0 else: comb_index_list = list(range(0, B_index + 1)) return OneToMany, A, Bif __name__ == '__main__': A = [1662.52, 4995.05, 45.3, 1879.08, 5044.86, 1219.7, 687.54, 663.26, 3606.51, 1548.91, 3150.2, 1784.29, 6869.56, 1730.5, 3534.81, 4366.99, 332.12, 2950.2, 2070.39, 593.34, 3326.01, 640.93, 950.71, 3719.31, 6108.77, 1511.03, 1883.93, 872.05, 2694.8, 8904.43, 5724.2, 8622.4, 704.05, 2925, 9658.56, 284.53, 2640.42, 5397.37, 9039, 6580.17, 6577.26, 7382.3, 2781.23, 1108.03, 2498.64, 1254.66, 578.78, 423.4, 2058.73, 3540.63, 3324.07, 863.31, 205.87, 9959.6, 3049.25, 7570.38, 2817.15, 9615.83, 194.22, 450.59, 3076.44, 382.61, 170.91, 2712.06, 423.4, 1298.97, 365.13, 2771.03, 275.58, 3629.97, 354.45, 4569.76, 2470.47, 1384.79, 1181.83, 1386.73, 4305.86, 2998.76, 705.99, 2489.07, 2695.68, 4106.78, 2105.34, 9303.26, 5803.96, 469.04, 534.11, 22097.8, 1765.21, 8329.12, 8417.12, 6360.71, 5901.37, 10156.8, 2646.25, 1076.95, 5429.69, 5758.62, 13216.3, 2276.26, 970.13, 1833.44, 6809.35, 2614.2, 1786.82, 509.65, 2862.81, 1580.95, 7461.93, 2653.56, 758.43, 6351.97, 2811.34, 2204.4, 5232.29, 9084.65, 6577.26, 6811.75, 477.78, 891.63, 493.32, 1165.32, 354.45, 1823.73, 1254.66, 5979.16, 3673, 377.76, 2705.48, 552.56, 463.32, 1786.82, 578.78, 1300.26, 3125, 292.5, 1130.36, 816.7] B = [32554.1, 16586.4, 14145, 13820.3, 13721.8, 12309.2, 12080.5, 11982, 11361.9, 10438.3, 10318.2, 10202.4, 10156.8, 9959.6, 9658.56, 9421.61, 9237.1, 8904.43, 8299.02, 7664.67, 7461.93, 7173.52, 6899.67, 6721.95, 6580.17, 6464.25, 6360.71, 6355.85, 6035.39, 5911.09, 5696.73, 5477.98, 5397.37, 5276.96, 5239.86, 5234.23, 5125.47, 5114.08, 5066.23, 5044.86, 4945.81, 4864.86, 4759.36, 4710.81, 4622.44, 4569.76, 4477.74, 4326.66, 4323.34, 4316.13, 4256.75, 4164.17, 4139.55, 4093.19, 4078.62, 3883.43, 3856.24, 3828.08, 3807.68, 3805.74, 3797, 3767.87, 3767.87, 3719.31, 3665.9, 3626.09, 3618.32, 3609.58, 3601.81, 3370.69, 3315.34, 3138.6, 3125, 3093.92, 3076.44, 3049.25, 3021.09, 3016.24, 3013.92, 2991.96, 2985.16, 2925, 2905.53, 2856.01, 2841.44, 2798.71, 2796.3, 2771.03, 2734.62, 2712.06, 2705.48, 2668.58, 2653.56, 2653.05, 2627.8, 2617.29, 2598.57, 2587.01, 2570.5, 2529.54, 2528.74, 2507.38, 2498.64, 2498.64, 2431.63, 2386.96, 2385.31, 2367.54, 2348.12, 2346.83, 2323.84, 2320.93, 2289.85, 2284.03, 2276.26, 2265.28, 2254.89, 2253.92, 2242.27, 2218.32, 2217.02, 2216.05, 2191.77, 2148.07, 2118.89, 2113.11, 2105.34, 2102.43, 2097.58, 2086.89, 2073.3, 2070.39, 2058.73, 1998.52, 1938.36, 1932.49, 1924.72, 1924.72, 1913.07, 1907.24, 1904.33, 1901.41, 1901.41, 1890.73, 1889.55, 1879.08, 1875.19, 1859.66, 1848.97, 1833.44, 1823.73, 1814.99, 1814.67, 1807.22, 1797.51, 1786.82, 1786.82, 1782.94, 1767.4, 1747.98, 1744.1, 1730.5, 1716.9, 1713.99, 1682.92, 1672.23, 1664.42, 1662.52, 1648.53, 1637.27, 1580.95, 1579.98, 1579.01, 1575.12, 1567.36, 1550.25, 1511.03, 1478.01, 1447.29, 1432.37, 1403.24, 1397.41, 1386.73, 1374.11, 1374.11, 1368.28, 1357.6, 1337.2, 1316.81, 1310.01, 1298.97, 1291.56, 1287.68, 1279.91, 1277.97, 1276.03, 1254.66, 1254.66, 1251.75, 1219.7, 1216.79, 1206.11, 1202.22, 1196.4, 1193.48, 1181.83, 1180.86, 1176.97, 1170.18, 1165.32, 1156.58, 1138.13, 1130.36, 1130.36, 1112.88, 1108.03, 1093.46, 1087.63, 1085.69, 1085.69, 1084.59, 1060.02, 1059.47, 1059.47, 1047.82, 1046.85, 1046.33, 1044.81, 1040.05, 1036.16, 1033.25, 1031.31, 1031.31, 1003.15, 994.41, 984.7, 970.13, 962.36, 961.39, 950.71, 950.71, 934.83, 931.28, 916.72, 893.41, 891.63, 891.63, 889.84, 881.01, 879.82, 877.87, 872.05, 867.19, 863.31, 860.35, 844.16, 830.29, 821.55, 821.55, 816.7, 815.72, 811.84, 799.03, 796.3, 796.3, 792.42, 791.45, 791.45, 786.24, 781.74, 778.82, 769.11, 755.82, 755.82, 753.57, 734.15, 729.3, 704.05, 703.22, 703.22, 703.08, 701.13, 696.28, 689.13, 689.01, 687.54, 680.74, 677.83, 671.03, 663.26, 659.88, 658.41, 657.43, 648.69, 645.78, 640.93, 635.1, 623.45, 615.68, 605.55, 604.14, 596.26, 594.95, 593.34, 593.05, 593.05, 592.37, 578.78, 578.78, 570.04, 570.04, 568.09, 564.21, 561.49, 560.32, 553.53, 552.56, 551.58, 551.07, 546.73, 541.71, 538.96, 534.11, 534.11, 531.02, 529.25, 529.25, 527.31, 527.31, 521.48, 519.54, 516.63, 510.12, 509.65, 504.97, 504, 502.06, 498.17, 498.17, 497.2, 497.2, 494.29, 493.32, 487.49, 483.91, 483.54, 481.67, 471.95, 469.76, 469.04, 464.19, 463.32, 461.27, 450.59, 448.65, 445.73, 440.88, 439.91, 437, 429.23, 423.4, 423.4, 421.46, 419.52, 418.54, 415.63, 414.66, 414.66, 412.72, 405.92, 398.15, 397.18, 395.24, 392.32, 388.44, 387.47, 387.47, 383.58, 383.58, 383.58, 383.58, 382.61, 381.64, 380.67, 377.76, 377.76, 365.13, 365.13, 365.13, 364.16, 363.19, 363.19, 362.22, 362.22, 360.28, 354.45, 354.45, 343.77, 343.77, 341.83, 341.83, 340.47, 337.94, 332.12, 332.12, 332.12, 331.15, 326.29, 325.32, 321.75, 315.61, 312.69, 308.81, 307.84, 307.84, 307.84, 305.9, 301.3, 299.61, 299.52, 286.47, 285.5, 284.53, 282.59, 274.82, 272.88, 270.94, 256.37, 255.4, 249.57, 248.6, 232.09, 231.12, 222.38, 220.44, 220.44, 220.44, 213.64, 205.87, 203.93, 194.22, 194.22, 193.25, 191.31, 183.54, 170.91, 168.85, 165.09, 143.72, 118.64, 97.11, 94.2, 70.01, 50.5, 49.42, 45.3, 44.46, 32.76] print(len(A), len(B)) OneToOne, A_filter, B_filter = find_one_to_one(A, B) print(OneToOne, len(A_filter), len(B_filter)) OneToMany, A_filter, B_filter = find_one_to_many(A_filter, B_filter) print(OneToMany, len(A_filter), len(B_filter))]]></content>
</entry>
<entry>
<title><![CDATA[尝试使用sklearn自动进行多模型预测并计算权重]]></title>
<url>%2F2016%2F12%2F01%2Fscikit-learn-about-weight%2F</url>
<content type="text"><![CDATA[待解决的问题在拥有多个模型的情况下,是否可以通过给多个模型分配权重(weight),使得加权后的多模型预测结果要好于单模型? 思路 是否存在通用的多模型weight计算方式? 如果没有,是否存在其他选取模型的方式? 如果权重只能人为设置,增加权重提高拟合度的方法是否可行? 如果权重能自动计算,能否在实际数据训练中增加拟合度? 解决方向 查找相关论文资料,确认了使用多模型同时计算加权的方式不常见。更多的是对单模型做优化以提高拟合度。简单做法是取所有模型拟合度相加等比放大/缩小到1,放大/缩小系数k作为权重。 sklearn中存在一个分类器VotingClassifier,往这个分类器中添加多个模型,可以根据训练集计算得分(score,拟合度)最高的模型,并以此模型做预测。 人为设置方式不可取,调整者需要很丰富的经验和大量测试时间。故采用决策树的方式,自动调整权重,得到与训练集拟合度最高的结果为合适方案。同时,此方案需要大量的样本数据才能拟合准确,否则会出现过拟合or仅在特定训练集表现优秀的情况。 试验假设存在三个模型A B C,训练集train_set。 简单权重计算训练集拟合得分Sa, Sb, Sc。权重计算为 当存在 Si<=0 时,该模型的权重Wi = 0,不计算结果。 Ssum = Sa,Sb,Sc相加。 权重 Wi = Si / Ssum。 此方式得到的权重,在实际计算中未能有效的提升预测结果的拟合度,表现与使用单模型相差不大,整体上表现略逊于拟合度>0.5的模型。 sklearn分类器将模型放入sklearn分类器进行模拟时发现,分类器选取要求每个模型拟合的训练集在数据清洗组合后都是同维的,才能进行比较。而目前使用的模型:支持向量机(SVR),隐性时间序列(HiddenPeriod),需要的训练集是完全不同维度的(SVR:28, HP: 1)。且将来添加其他模型需要训练的维度也大概率是不同于两者。故此方案不可行。 决策树目前由于数据数量和边界条件不明,暂时无法做拟合度测试。待重启 结论以目前的研究和试验看来,权重的方式对拟合度的提升不明显,效率提升不如对单模型进行优化。故权重计算的开发可暂时延后。 另一种思路?不采用权重同时训练所有的模型,而是先取某个模型进行训练,再针对残差使用另一个模型进行训练。这种思路会使得单模型有针对性的处理特定数据训练集,是否能提高拟合度有待检验。]]></content>
</entry>
<entry>
<title><![CDATA[单元测试(Unit Test)覆盖级别]]></title>
<url>%2F2016%2F12%2F01%2Funit-test-standard%2F</url>
<content type="text"><![CDATA[这是我个人从外部文档和工作项目中总结,当开发单元测试时,根据项目级别不同需要达到级别标准。 级别分类 Level1:正常流程可用,函数在输入正确的参数时,会有正确的输出。 Level2:异常流程可抛出逻辑异常,输入参数有误时,不能抛出系统异常,而是用自定义的逻辑异常通知上层调用代码的错误。 Level3:极端情况和边界数据可用,对输入参数的边界情况也要单独测试,确保输出是正确有效。 Level4:所有分支、循环的逻辑走通,不能有任何流程是测试不到。 Level5:输出数据的所有字段验证,对有复杂数据结构的输出,确保每个字段都是正确的。 使用标准一般项目只要做到Level2~3即可。数据量庞大的项目需要做到Level4。高密高危项目需要做到Level5。]]></content>
</entry>
<entry>
<title><![CDATA[Welcome To My Maze!!!]]></title>
<url>%2F2016%2F11%2F22%2Fself-welcome%2F</url>
<content type="text"><![CDATA[欢迎来到迷宫 想要我的财宝吗?想要的话可以全部给你,去找吧!我把所有财宝都放在那里! 这里是存放个人技术文章的小仓库,也会收录一些其他站点文章作备份(字典)。浏览文章中偶尔会遇到奇怪的东西,不感兴趣的话请略过。想与作者联系的请参考左侧栏选择适合你的联系方式,欢迎大家来找茬! 近期任务:监控特定直播房间开播状态,并获取弹幕。]]></content>
</entry>
<entry>
<title><![CDATA[直播平台爬虫项目介绍]]></title>
<url>%2F2016%2F11%2F22%2Fabout-living-mining%2F</url>
<content type="text"><![CDATA[项目介绍项目实现爬虫、数据分析,主要是爬取直播(斗鱼、Bilibili)收集数据,后续开发分析功能。代码采用GPL v2协议,开源发布在 Github上。项目部署在站点:http://www.zhengwentao.com。项目是在个人兴趣下用业余时间写的,技术还欠缺火候。使用中有bug或更新建议,欢迎提issue。 功能 爬取指定直播站点的频道、房间信息,记录到数据库。 WEB显示爬取内容,以及根据人气值的排名情况。 通过OAuth2可注册用户(支持:github)。 登陆后可根据关键字搜索房间。 根据记录的房间人气值历史信息,预测未来人气值变化趋势(开发中)。 开发历史v2.0(master分支开发) 运行中采用框架: Web服务:Flask(web框架) + Vuejs(页面模板) + Bootstrap(样式)爬虫:Scrapy(爬虫工厂) + Redis(管道) + Crontab(定时任务) 爬取站点:斗鱼 bilibili v1.0(2016-08-15开发完毕)采用框架: Web服务:Flask(web框架) + Jinjia2(页面模板) + Bootstrap(样式)爬虫:Requests(生产请求) + Gevent(异步) + Celery(定时任务) 爬取站点:斗鱼 熊猫 战旗 bilibili 升级原因:采用Gevent协程处理的方式会导致进程长时间占用CPU,由于机器性能不高导致无法处理WEB请求无法访问页面。]]></content>
</entry>
</search>