Check out my video!!! – 0x00-HTB-GetInviteCode My input method is broken. So everything from now on stays English. I don’t bother fix it any more, because I google 😀 Hacking is like solving math problems, the thoughts behind every move is the most important things to learn and absorb. I choose to pivoting in my…
Author: 0pr
ZanBuild 工程日记
2017-11-13 14:51 之前三期算是练手, 整个项目的整体流程都已经很清楚了, 那么从第四期开始, 就要在代码质量和机构层面来搞一些事情了. 先来回顾一下第三期的编码过程. 可以说看了那几篇关于 JS 的文章有点蛋疼. 十月中旬的那两周把第三期的代码折腾来折腾去, 最后还是发现了很多问题. 作罢, 现在已经全部改回到默认的 React 写法了. 总有那么点不甘心, 迫于时间, 不然还想重新研究一下到底哪里除了问题 (个人感觉上来说, 还是只从 React.Component.prototype 复制属性过来, 而没有任何地方去执行父类初始化带来了那些无法更新等的一系列问题). 第三期结束之后, 大致有如下几点问题: 感觉最不好的地方就是代码结构不好, 没有很好地复用 组件封装有问题, 后面想复用组件很困难 由于没有复用, 重复代码是很多的 这一点可能是看文章的副作用, 现在很抵触 extends 继承… 总不想写 Base 然后去继承一下 (比如 Build Create 等几个模块中的代码很多都是可以复用的, 当时由于抵触没有去写, 现在要想办法找到一个在 React class 中能用组合的方式) 今天分析完了页面 UI 和新一起的整个逻辑. 感觉又是一轮重写. 这次准备 80% 时间设计,…
Debian 9 Stretch发布
Debian 9发布了,代号”Stretch”。 看官方发布的信息。 Debian 8的用户,可以dist-upgrade了。 又想起来Ian Murdock自杀的悲剧,希望Debian越来越好。 直通Debian下载页面。
Android性能最佳实践
最近看了谷歌官方关于Android性能最佳实践的部分,感觉应该要记下来才行。这里面有很多不看不知道的东西,我也为一些比较难懂的点增加了一些额外阅读的链接。刚总结完了JNI的小贴士,往后几天会陆续在这篇文章中把性能最佳实践这一部分补充完整。 后面还有安全最佳实践,权限最佳实践等部分,每一部分一篇文章,都会分开记录下来。 性能小贴士 这里介绍了一些小优化,可以提升app的整体性能。但是不一定会带来性能的飙升。选择正确的算法和数据结构是获得良好性能的首要任务。这里的小优化都是一些通用的编码实践,实现高效代码。 实现高效代码有两个基本规则: 不要重复造轮子 不要无谓分配内存 不要创建不必要的对象 创建对象总是要付出代价的。当我们创建越来越多的对象的时候,我们其实在强制地让垃圾回收器更加频繁地工作。这会造成类似于『打嗝』一样的波动,影响用户体验。 因此,要避免任何不必要的对象创建。以下是一些建议: 比如说,如果一个方法要返回String对象。Java内部实现的时候,String最后都是会被加到StringBuffer中的,因此不需要在代码中创建一个临时的StringBuffer或者StringBuilder对象来append字符串,直接用String就好了。 从字符串中截取子字符串的时候,不要创建新的String对象去存放原字符串的拷贝,可以选择直接return substring就好。 更加影响性能的一些点在于数组的使用上: int类型的array比Integer类型的array性能更好;同时,想方设法避免(int, int)这样多维数组的使用,将多维数组降成一维从而获取性能提升; 总结一下,尽量避免临时对象的创建,这样能减少垃圾回收器的运行次数,提升用户体验。 尽可能使用static而不是virtual 如果一个方法不需要访问这个类的成员,那么用static修饰这个方法。这样一来,大致上会有15%-20%的访问速度提升。 这里stackoverflow有个针对于这个问题的很好的解释 使用static final修饰常量 使用statis final修饰常量,能提高访问速度。 这里涉及到java的编译原理,做不了深入解释了。 要注意的是,这只对原始类型数据以及String常量有效。 避免在类的内部使用Getter/Setter方法 在C++等语言中,(i = getCount())这样的代码是很好的编码习惯,编译器会提升执行效率。 但是在安卓中,使用这样的方式是很糟糕的想法。在安卓中调用Virtual Method差不多就像寻找成员变量一样消耗性能。在类中,直接访问成员变量而不要使用Getter方法。 没有JIT编译的情况下,直接访问成员的速度将3倍快于调用Getter方法。拥有JIT编译的情况下,直接访问成员变量变得和访问局部变量一样快捷,将达到7倍快于调用Getter方法。 这是一片关于Java中Virtual Method的文章 使用增强for循环 除了ArrayList的遍历之外,增强for循环的性能是最好的。无论有没有JIT编译支持,在ArrayList的遍历上使用手写for循环,都将3倍快于增强for。 但是在其他容器上,增强for的性能在没有JIT的情况下快于手写for循环,在有JIT的情况下等同于手写for循环。 鉴于更少的代码,在除了ArrayList的地方,都使用增强for。 看下面的情形: zoo()方法是最慢的,使用了手写for循环,并且每次循环都要获取array长度; one()方法快一些,不用每次都获取array长度了; two()方法最快,使用了增强for(这里不是ArrayList)。 记住在非ArrayList的情况下用增强for。 使用默认包访问权限而不是私有private权限 考虑如下情形: 内部类Inner访问了外部类的成员变量mValue和成员方法run,语法上是没有问题的,运行结果也正确。 但是,因为mValue和run方法被private修饰,VM是禁止直接访问一个类的私有成员的,因为Foo 和Inner是两个不同的类。 为了能使内部类访问外部类的私有成员,编译器生成了如下两个方法: 因此,无论是访问mValue还是run,都调用了其中一个方法。 在前面讲到了,在同一个类中要访问成员或者方法最好的方式是直接访问,而不是通过方法调用。因此,这里就是性能损耗的地方。 最好将private去掉,也就是使用默认权限。但是这样一来其他同一包中的类就能访问这些成员了。 最好的办法就是不要写这样的代码了。 避免使用浮点…
Android设计与实现-卷1-JNI框架基础
看完了『Android设计与实现』第一部分,做了笔记,但是发现还少一张图能把JNI层的方法声明和调用关系明确表示出来的。花了点时间把Log系统的方法声明和调用关系整理出来了,看着舒服多了,也有条理。 红色两块是Log系统的Java文件和对应的C++文件。所有的方法以及调用关系从这两个矩形开始。android_util_Log.java包含本地方法声明,android_util_Log.cpp包含了本地方法的实现、Java本地方法和C++方法实现之间的关系映射以及将这种映射关系告知Dalvik虚拟机的过程。
Tensorflow-3-使用RNN生成中文小说
这篇文章不涉及RNN的基本原理,只是从选择数据集开始,到最后生成文本,展示一个RNN使用实例的过程。 对于深度学习的应用者,最应该关注的除了算法和模型,还应该关注如何预处理好自己的数据,合理降噪,以及如何在数据量不同的情况下选择合理的超参,来达到最理想的训练结果。 在经过近三个月的学习之后,我打算使用Tensorflow,创建一个LSTM RNN模型,使用中文小说作为数据源,训练RNN来生成中文小说文本。平时做练习训练数据都是英文,我想看看换成中文之后会是什么结果,能不能写出一些语义通顺的句子。 数据选取的是起点中文网的获奖历史小说『寒门首辅』,作者一袖乾坤。 整个notebook在我的github上,感兴趣的同学可以下载使用,不断尝试训练自己喜欢的风格的小说生成器。强烈建议大家使用notebook进行尝试,可以实时看到每一步的输出,学习效果更好。 以下就是整个应用过程。 来试试用起点中文网的历史小说『寒门首辅(一袖乾坤 著)』来做训练数据,看看这个RNN网络能产生一些什么样子的文本。 尝试过程中必遇到问题,也借此加深一些对RNN的理解。 首先我从网上下载到了『寒门首辅』的txt版本,打开时候发现有很多空行,还包含了很多不必要的链接,看起来是这样的。 预处理一下数据。 读入数据 设置一下要用多少个字来训练,方便调试。这里先用100000字进行训练 看看有多少行 先看看前15行是什么内容 把『章节目录』之前的行全部砍掉,一大堆没用的东西。 再来看看,第一行应该就进入正题了。 我查看了一下,这个小说一共有129万字左右。先把空行去掉吧。去掉空行之后应该就只有一半左右的行数了。 打印前20行看看什么情况 下一步,把每行里面的『空格』,『[]里的内容』,『<>里的内容』都去掉。 看下情况如何,打印前20句话。 可以看到空格都没了。下一步用正则去掉『[]』和『<>』中的内容,像上面的什么『[棉花糖小说网]』这些的,后面还有一些是包含在『<>』里的,一并去掉。 打印看效果 『[]』的内容已经没了。下一步去掉『<>』中的内容,方法同上。 下一步,把每句话最后的『……』换成『。』。 打印看效果 最后,还是把每句话里面包含的空格,都转换成『,』,就像『章节目录 第一章』,换成『章节目录,第一章』,感觉这一步可有可无了。 貌似还忘了一个要处理的,我们看看最后20行的情况。(如果你是用全文本来训练,最后很多行文本中会包括\r这样的特殊符号,要去掉。这里只用了100000字,所以看不到有\r的情况。)。如果有\\r的情况,用下面的方式去掉。 到这里数据就处理完了。再看看有多少行数据 因为模型只认识数字,不认识中文,所以将文字对应到数字,分别创建文字对应数字和数字对应文字的两个字典 创建一个符号查询表,把逗号,句号等符号与一个标志一一对应,用于将『我。』和『我』这样的类似情况区分开来,排除标点符号的影响。 预处理一下数据,并保存到磁盘,一遍下次直接读取。 读取我们需要的数据。 检查改一下当前Tensorflow的版本以及是否有GPU可以使用 这里的数据量还是很大的,129万左右个字符。建议使用GPU来训练。或者可以修改代码,只用一小部分数据来训练,节省时间。 正式进入创建RNN的阶段了。 我们的RNN不是原始RNN了,中间使用到LSTM和word2vec的功能。下面将基于Tensorflow,创建一个带2层LSTM层的RNN网络来进行训练。 首先设置一下超参。 创建输入,目标以及学习率的placeholder 创建rnn cell,使用lstm cell,并创建相应层数的lstm层,应用dropout,以及初始化lstm层状态。 创建embedding layer,提升效率 创建rnn节点,使用dynamic_rnn方法计算出output和final_state 用上面定义的方法创建rnn网络,并接入最后一层fully_connected layer计算rnn的logits 那么大的数据量不可能一次性都塞到模型里训练,所以用get_batches方法一次使用一部分数据来训练 创建整个RNN网络模型 开始训练模型 将使用到的变量保存起来,以便下次直接读取。 下次使用训练好的模型,从这里开始就好 要使用保存的模型,我们要讲保存下来的变量(tensor)通过指定的name获取到…
Tensorflow-2-Tensorboard使用
一、概述 机器学习如此复杂,训练模型的时候,摸不清背后到底是如何运行的。自己设置的参数和关键变量,如果能看到在训练时的变化情况,可以为后面的参数调优阶段提供很大的便利。 Tensorboard就是这样一个工具。 它刻意将模型抽象成图像,tensor每一步是如何流动的,一目了然。 通过适当的代码设置,还能将指定的关键变量在训练时的变化情况绘制成曲线图,以便训练完成后观察变量的变化情况,来更加准确定位问题。 这篇文章简单介绍一下tensorboard的基本用法。 二、Tensorboard使用 tensorboard(以下简称tb)的操作,从创建一个FileWriter开始。 在接下来的代码中,我参照CS231N课程的数据集例子,用tensorflow(以下简称tf)写了一个Logistic Regression,并以此来说明tb的基本用法。 用到的notebook在我的github上可以找到。使用之前,请确保执行 来创建和我一样的运行环境。如有问题,可以留言或者ISSUE。 创建好环境之后,运行 激活conda环境,然后运行 来使用本例中的notebook。 下面的示例程序用tf做了一个两层的分类网络。将下图中的数据集分类。 最终分类效果是这样的。 tb的使用,大致归纳为三步: 调用tf中的FileWriter将自己关注的数据写到磁盘 在命令行使用tensorboard –logdir /path/to/log启动tb的web app 然后在本地浏览器输入localhost:6006来使用tb 下面具体看一下怎么使用。 1.生成模型图 生成模型图只需要一句话就行。比如说,现在已经初始化好了变量,处理好了数据,部分代码如下: 准备开始训练的时候,加上一句 例如,在session开始的时候添加就好。 我们要看整个模型的图像,因此传入session.graph对象。 这时,来到命令行,切换到notebook所在的目录,然后执行 logs/summary就是代码中定义的目录路径。tb启动后会提示到浏览器用localhost:6006去打开tb应用。 在浏览器打开后,切换到GRAPH标签,看到的模型图时这样的。 这个时候其他标签还没有内容,因为还没有在代码中进行添加。 上面的图片,就是现在这个模型的原始图像,没有进行任何分组和加工。看起来很乱,有一些标签,例如slice什么的,都不知道是什么意思。 图中, 每条曲线代表tensor的流向 每个椭圆代表一个操作,如add,matmul 每个圆角矩形代表一组操作,可以双击放大,看到这个组里面的细节 整张图片可以放大缩小,随意拖动;点开每个节点,右上角都会有这个节点的详细信息 下面来加工一下,为模型图分组,让图像更加清晰有条理。 2.使用name_scope分组 调用tf.name_scope()方法来为graph分组。 我想清楚看到 输入Inputs 标签Targets 两组Weight和bias变量 两个隐藏层的输出Logits_1和Logits_2 损失函数loss 训练准确率Accuracy以及 整个训练过程Train 示例代码如下。 输入Inputs 标签Targets 两组Weight和bias变量…
自制Android RSS阅读器
这个问题困扰我挺久了,android端找不到一款好的RSS阅读器。我就想简简单单打开自己订阅的RSS每天看一看,没有注册,没有广告,就简简单单的。终于抽了两天时间出来写了个BETA。 所有代码都放在我的Github上了。 记录一下开发过程中遇到的一些问题。 1. RecyclerView处在ConstraintLayout中出现的视图问题 视图的问题如图。 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TwCD6atd-1587400775279)(http://img.blog.csdn.net/20170602222804432?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVpc2VqaXVodWNoZQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)] 在adapter的onCreateViewHolder()方法中,就是按照 这样来写的。子视图的高度也都是确定的。如果这么简单就好了。问题照旧。 尝试了很久,结果症结出在ConstraintLayout和RecyclerView一起使用上。 上图中是一个fragment,有问题的fragment的根布局如下: 因为其他很多地方我都排查过了,所以对这个布局心生怀疑。 我就把ConstraintLayout改成了FrameLayout,修改后的布局如下: 问题解决。 2. 对RSS的XML文档的解析 读取RSS中的内容其实就是解析一下XML文档。 RSS的格式有个大概的标准,大致就是<channel>或者<rss>开头,然后是最外层的<title>, <link>, <description>的内容;紧接着就是<item>,代表每个子条目;每个<item>标签中也有相应的<title>, <link>, <description>节点。 比较了feed.yeeyan.org/select,zhihu.com/rss,http://www.read.org.cn/feed以及feed.androidauthority.com四个RSS,发现有三个问题: <link>标签的内容,可能包含在<link>的属性中,如:<link href=”http://…”> <description>标签有时候又叫<subtitle> <item>标签有时候又叫<entry> 因此在解析的时候,将这三个问题考虑进去,大部分的RSS应该都能解析了。 简单的应用,使用sqlite作为本地存储,如果重复添加已有的RSS,就相当于刷新RSS的内容。 目前还只有简单的添加RSS,浏览其内容的功能。 陆续还会抽空把刷新,进度条和 RSS补全库等功能加上。 代码希望对大家有用。有需要改进的地方,可以邮件我或者ISSUE。 上个截图:
关于Android Studio导入工程卡在Building Gradle上
有时候,我从github上拽下来一个工程,然后在导入的时候,就卡在Building Gradle那一步,进度条一直在读,但是就是没有反应,等急了要取消还取消不掉,必须强制退出。如下图。 我猜测是因为工程的gradle版本和本地的不一致,导致android studio要去下载相应版本的gradle,但是国外的网站真的是太慢了… 解决办法如下。 查看本地Gradle版本 Mac或者Linux用户,如果android studio正确安装的话,应该在home目录下有一个.gradle文件夹。 cd ~/.gradle/wrapper/dists 执行上面的命令查看本地gradle版本,如图。 修改目标工程的gradle/wrapper/gradle-wrapper.properties 在文件管理器中找到目标工程的gradle/wrapper/gradle-wrapper.properties文件,打开并修改版本号为本地任一gradle版本。 再次导入工程 再次导入工程,整个过程就很顺畅了。
Tensorflow-1-Tensorflow Moblie Android平台编译安装
之前就看到Tensorflow有手机平台的API了,今天终于抽了点时间出来鼓捣一下。 首先是把tensorflow克隆到本地一份。 既然是谷歌官方要求的,最好把–recurse-submodules加上,文档说可以避免一些数据结构序列化时的编译问题。 这是android demo的github主页。 准备编译 1.安装bazel bazel是谷歌自己的构建工具。tensorflow只能部分支持cmake或者gradle,而bazel是tensorflow工程的主要构建工具。 点这里下载Bazel。 Mac和Linux用户根据文档进行安装。Windows用户,按照官方建议到下面的链接下载demo的二apk文件,目前bazel在windows平台还处于试验阶段。 Windows用户点这里直接下载apk bazel安装成功与否,用bazel version检查版本即可。 2.下载NDK 点这里下载最新版本NDK。 最好下载r12b版本的,最新的r13b可能与bazel有兼容问题。 下载完成后解压到自定义目录,然后在~/.bash_profile(linux在~/.bashrc)下添加环境变量。环境变量的添加过程大家百度一下吧,不是这里的重点。 3.下载>=23 Android SDK Tensorflow Android Demo必须在大于等于23的API环境中编译。可以打开Android Studio中的SDK Manager来安装最新的SDK。 4. 编辑Tensorflow根目录下的WORKSPACE文件 回到tensorflow根目录,(当前在android目录就往上两级)。打开WORKSPACE文件。 在文件开头部分找到 这两部分定义了SDK和NDK的路径,把/path/to/your的部分改成系统相应的路径。然后将每一行前的注释去掉。如下: 开始编译 在tansorflow根目录执行, 进行编译,变异过程如下: 一切顺利的话,编译成功,如下图: 安装APK DEMO 变异成功之后bazel会在bazel-bin目录下面生成apk文件。用数据线连上手机,执行 即可安装到手机。 DEMO截图 TF Classify 图片分类的Demo。可以看到tf识别出了台式电脑和显示器。 TF Stylize 这个Demo很好玩,不只是将一张图片的风格渲染到摄像头,还能通过调节来综合两张图片的风格。 点击左上角的数字按钮,可以从128一直选到720。刚开始以为这个数值跟训练过程中的神经元数量有关。后来想想这些模型应该都是训练好了的,移动平台还没有能力进行这样的训练。看源码得知这个就是最终呈现的图片的尺寸,越高图片越清晰。但是相应的,对手机性能的要求就越高。我在魅族pro 6 plus上测试,选择256之后,就开始卡顿的厉害,720的话,定在一个点上大概5-7秒才能看到渲染之后的图像。 总结 市面上已经有很多运用深度学习的应用的例子。但是大多数都是只能让用户使用已经训练好的模型,而无法让用户自定义。比如我想用我自己喜欢的两张图片作为风格,来渲染视频,而不是图库中已有的。受限于移动平台自身的计算能力,目前还做不到;而把计算放到云端,用户体验又太差(prizma网络不好的时候要等很久,还可能失败…)。 期待用量子计算机来做深度计算哈哈哈~