起因:某天晚上看一个科技评测节目,该节目宣称只要能够在视频中找到视频中插入的某一帧无关内容,就可以获得相应的奖品。我想了想应该是可以用代码实现的:
使用python3的一个工具you-get就能够做到。不过稍有曲折,我使用you-get去下载B站和优酷的视频都下载失败了,好在在该测评节目微博上找到了另外一个视频资源链接,使用you-get顺利下载下来,视频是640×360的,十分钟内容一共60M的MP4格式。
我先按照原样抽离,即抽离成640×360的图片,一共生成了8,988个文件,大小1.80 GB,不禁感慨视频压缩格式确实厉害啊,这压缩了多少倍啊,另外我考虑到可能更小的缩略图应该也拥有足够的分辨特征,所以也按照64×36的分辨率抽离了更小的缩略图
640×360逐帧抽离的图片截图
64×36逐帧抽离的图片截图
图像相似度算法我没具体研究过,直接用的github上面的项目:https://github.com/MashiMaroLjc/Learn-to-identify-similar-images
一共有有四种算法,具体中文的文章可以参看链接:
https://segmentfault.com/a/1190000004467183
我使用了不同的算法得到的不同的结果:
由于之前excel的制图删掉了,只能用当时程序计算的文本信息凑合了,计算出来的相似度大致就是如下的数字列表。
其实就是根据特征去拟合一条折线,能够正确反映出异常的关键帧在哪里。
其实这一步,我做了两三个小时,为了选择最佳的算法和最佳的效果,只有下图能够直截了当的反映出异常的帧在哪里,后来我想了想,如果加入跳帧的对比,比如第一帧和第三帧的特征,就能够更加准确的找到关键帧的位置。
http://mp.weixin.qq.com/s/K2YCm8QwnpI7dNTs048Jbg
叠加两个声音,并按照第一个声音的长度截取音乐,然后输出16k,单声道,声音质量为4的音乐:
ffmpeg -i example1.wav -i example2.wav -filter_complex amix=inputs=2:duration=first -ar 16k -ac 1 -q:a 4 output.wav
参考:https://ffmpeg.org/ffmpeg-filters.html
重复某个音频文件4次并截取80秒的音频数据
ffmpeg -stream_loop 4 –I example.wav -c copy -t 80 output.wav
从00:00:15开始截取音频、视频,截取5s,然后原样输出到文件中
ffmpeg -ss 00:00:15 -t 00:00:05 –I example.mp4 -vcodec copy -acodec copy output.mp4
pcm(已知pcm文件格式为16k 16bit 单声道)转换到固定格式的wav文件中
ffmpeg -f s16le -ar 16k -ac 1 -i tts_file_119.pcm -ar 16k -ac 1 tts_file_119.wav
对音频文件增加渐入渐出过滤效果(淡入从0秒开始,持续10秒,淡出从50秒开始,持续10秒,设定音乐音量为2, -y为覆盖已存在文件)
ffmpeg -i input.mp3 -af “afade=t=in:ss=0:d=10,afade=t=out:st=50:d=10,volume=volume=0.2” -t 60 output.mp3 –y
更多声音过滤器:http://ffmpeg.org/ffmpeg-filters.html
设定背景音乐,循环播放并增加淡入淡出效果
ffmpeg -stream_loop 4 -iinput.wav -af “afade=t=in:ss=0:d=10,afade=t=out:st=50:d=10,volume=volume=0.2” -t 80 output.wav
一般来讲 ffmpeg的文件后缀都是自适应的,比如你设置的输出格式是mp3,那么文件就能自动转换成该格式的文件,具体的采样率等参数需要单独去设置调整。
TypeError: not enough arguments for format string
使用Python连接数据库的时候,采用的非常非常轻量级的torndb,甚至于事务都不支持,所以用”select * from table where condition=’%s'” % (condition,)
因为用的比较原生,所以各种问题接连不断,最最恶心的就是字符串转义造成的一些列原因.
先采用
condition = re.escape(condition)
能对特殊字符进行转义,但是还是有问题,又报错TypeError: not enough arguments for format string 直到认真看输入的condition字符串的时候,才发现问题所在之处: condition中有% 需要替换%为%%才能正常执行,
condition= condition.replace('\%', '%%')
其实标题有问题,不只是操作数据库,只不过在操作数据库时候,忽略的字符串本身的内容,一直在错误的寻找解决方案.
从今天开始,准备更一个读书笔记系列的博客,一方面把看到书中有用的东西记录下来,方便自己日后查阅,另一方面也是为了自我监督,多读书,多学习.
机器学习如何解决分类问题?
机器学习如何解决分类问题,它的主要任务是将实例数据划分到合适的分类中。机器学习的另一项任务是回归,它主要用于预测数值型数据。大多数人可能都见过回归的例子——数据拟合曲线:通过给定数据点的最优拟合曲线。分类和回归属于监督学习,之所以称之为监督学习,是因为这类算法必须知道预测什么,即目标变量的分类信息。
用于执行分类、回归、聚类和密度估计的机器学习算法
监督学习的用途 | |
k-近邻算法 | 线性回归 |
朴素贝叶斯算法 | 局部加权线性回归 |
支持向量机 | Ridge 回归 |
决策树 | Lasso 最小回归系数估计 |
无监督学习的用途 | |
K-均值 | 最大期望算法 |
DBSCAN | Parzen窗设计 |
如何选择合适的算法?
首先考虑使用机器学习算法的目的。如果想要预测目标变量的值,则可以选择监督学习算法,否则可以选择非监督学习算法。确定选择监督学习算法之后,需要进一步确定目标变量类型,如果目标变量是离散型,如是/否、1/2/3、A/B/C或者红/黄/黑等,则可以选择分类算法;如果目标变量是连续型的数值,如0.0~100.00、-999~999或者+∞~-∞等,则需要选择回归算法。
如果不想预测目标变量的值,则可以选择非监督学习算法。进一步分析是否需要将数据划分为离散的组。如果这是唯一的需求,则使用聚类算法;如果还需要估计数据与每个分组的相似程度,则需要使用密度估计算法。
其次需要考虑的是数据问题。我们应该充分了解数据,对实际数据了解得越充分,越容易创建符合实际需求的应用程序。主要应该了解数据的以下特性:特征值是离散型变量还是连续型变量,特征值中是否存在缺失的值,何种原因造成缺失值,数据中是否存在异常值,某个特征发生的频率如何(是否罕见得如同海底捞针),等等。充分了解上面提到的这些数据特性可以缩短选择机器学习算法的时间。
开发机器学习应用程序的步骤
此外还需要为机器学习算法准备特定的数据格式,如某些算法要求特征值使用特定的格式,一些算法要求目标变量和特征值是字符串类型,而另一些算法则可能要求是整数类型。后续章节我们还要讨论这个问题,但是与收集数据的格式相比,处理特殊算法要求的格式相对简单得多。
这一步的主要作用是确保数据集中没有垃圾数据。如果是在产品化系统中使用机器学习算法并且算法可以处理系统产生的数据格式,或者我们信任数据来源,可以直接跳过第3步。此步骤需要人工干预,如果在自动化系统中还需要人工干预,显然就降低了系统的价值。
如果使用非监督学习算法,由于不存在目标变量值,故而也不需要训练算法,所有与算法相关的内容都集中在第5步。
k-近邻算法概述:
k近邻算法采用测量不同特征值之间的距离方法进行分类。
优点:精度高、对异常值不敏感、无数据输入假定。
缺点:计算复杂度高、空间复杂度高。 适用数据范围:数值型和标称型。
k近邻算法的一般流程
实施kNN分类算法:
对未知类别属性的数据集中的每个点依次执行以下操作:
kNN使用想法:
分别使用书中提供的kNN算法和scikit中的KneighborsClassifier算法进行运算,相同参数下,书中的kNN算法准度和时间都优于scikit的算法,本来以为K值的设置是没有什么意思的,仔细阅读代码发现,kNN的思想是找到一个点的周围邻居,然后画一个圈,这个圈中最多的分类就是预测的分类.故此算法有一定的去噪能力.至于kNN的实用性,感觉不是很大,因为计算太频繁了,而且没有累计,下次的新数据依然需要大量计算, 我个人很在意机器学习的累积效果,如果没有累积效果,那就是普通的算法.
推荐阅读: http://www.cnblogs.com/zichun-zeng/p/3995040.html
python以其强大和简洁的语言让人折服,那么究竟有多强大,多简洁呢?在今天学习python的过程中,我来举个例子。
in:将以下列表转化成{‘a’:1,’b’:2}的形式
var = [('a','A',1), ('b','B',2), ('c','C',3)]
方法1:
tmp1 = [] tmp2 = [] for i in range(3): val1 = var[i][0] val2 = var[i][2] tmp1.append(val1) tmp2.append(val2) tmpdict = {}.formatkeys(tmp1,0) for i in range(3) tmpdict[tmpdict.keys()[i]] = tmp2[i]
当然我有意的拉长了代码。
方法2:
tmp1 = [] tmp2 = [] for i in range(3): tmp1.append(var[i][0]) tmp2.append(var[i][2]) tmpdict = dict(zip(tmp1,tmp2))
采用zip压缩数组,然后转换成dict
方法3:
tmpdict = {i[0]:i[2] for i in var}
一句话循环并组成字典。
同样的还有很多地方用到,比如lambda,reduced,filter,cmp等这类函数的应用。能大大减少代码量。更有意思的可以查看:一行 Python 能实现什么丧心病狂的功能?
目标:在不删除python环境的情况下,安装一些常用的python库到windows中。
安装
VCForPython27 :windows下面vc库的安装软件。
Numpy : numpy windows下面的exe文件
scipy : scipy 的exe文件
matplotlib : pip 环境下的 whl 安装包,需要使用pip install 这个文件.whl 安装
下面工具还不熟悉,先不写描述了。
setuptools
python_dateutil
pyparsing
最近做项目使用scrapy,采用的是script的形式去写爬虫的,使用crawlspider去定义爬虫规则。
我先从数据库里面把我要读取的规则拿出来,采用的是单个频道写规则的形式,对每个列表页写一套规则,所以有next_page的规则。
sql = """SELECT id, weburl_id, name, allow_domains, start_urls, next_page, allow_url, extract_from, title_xpath, body_xpath, publish_time_xpath, source_site_xpath, enable FROM leiju_rules WHERE enable > 0"""
next_page分析形式是xpath提取链接,使用Rule不跟随(follow = False)。我的需求是我应该采集所有的页面,但是由于我想做成定时任务,就需要下次还使用这一套规则来运行爬虫,做到增量爬。这样的话就涉及到了内容的去重。开发的最开始,我才用的是pipline 通道去重,也就是当我产生一个request之后才开始判断这个内容我需要不需要,这样是很浪费服务器资源的。
if self.Redis.exists('url:%s' % item['url']): raise DropItem("Duplicate item found: %s" % item['url']) else: self.Redis.set('url:%s' % item['url'], 1) return item
然后我修改成采用downloadMiddleware下载中间件去控制访问,因为downloadMiddleware是可以控制在request访问之前的,加上Redis的过滤。
if Redis.exists('url:%s' % response.url): raise IgnoreRequest("IgnoreRequest : %s" % response.url) else: Redis.set('url:%s' % response.url, 1) return response
这时候又有一个问题了,就是我会把所有的访问都给记录下来,下次我连我写的起始start_urls都进不去了。本来寄托于从以下代码入手:
rule_list.append(Rule(LinkExtractor(restrict_xpaths=rule['next_page'])))
即希望通过next_page拿到下一页的链接,然后把这些链接排除掉,已经准备好了一个Redis库去存储这些url。
Filter = redis.StrictRedis(host='127.0.0.1', port=6379, db=2, password='pass123456')
然而实际在使用的时候发现我通过:
rule_list.append(Rule(LinkExtractor(restrict_xpaths=rule['next_page'])))
拿到的根本不是URL列表,而是一个Rule对象,里面包括了LinkExtarctor的Xpath规则。我甚至想通过response和xpath拿到链接之后在用redis存起来进行排除。
解决方法:
配合使用pipline和downloadMiddleware来轻松完成以上功能。
我先定义一个downloadMiddleware,用来拦截url,防止重复访问。
class IngoreHttpRequestMiddleware(object): """ 从下载器处开始拦截/过滤URL """ def process_response(self, request, response, spider): if Redis.exists('url:%s' % response.url): raise IgnoreRequest("IgnoreRequest : %s" % response.url) else: # Redis.set('url:%s' % response.url, 1) return response
然后定义一个pipline,用来保存最终流入pipline的item URL。
class FilterUrlPipline(object): """ use redis to fileter url """ def __init__(self): self.Redis = config.Redis def process_item(self, item, spider): self.Redis.set('url:%s' % item['url'], 1) return item
这样一来,我的一个列表页面的所有链接都进入到了downloadMiddleware中,但是通过pipline拿到了最终我要的终极页面,通过pipline保存item URL,然后下次的时候redis里面有了数据,就可以排除所有的符合的终极页面访问请求,这样就解决了。
已开源在github上面:https://github.com/fengxiaochuang/ScrapyDemo