前言
几年前看过《雨果》这部蒸汽朋克风格的电影,其中一个情节“小男孩的噩梦”给我留下了深刻印象,主角小男孩是个寡言而聪明的孩子,在身为工程师的唯一亲人父亲工伤去世后,接替亡父维护钟楼,整体和各种机械打交道,一天夜里,半梦半醒间,他发现自己胸膛可以打开,打开后里面是运转的齿轮和曲轴,原来自己是个机器人!!
我也有同样的梦境,屏幕上的代码奔涌而出,看似是机器自动写的,亦或是我就是一个自动写代码的机器人??
----咳咳咳,扯远了,回到现实,推出本文正式主题:《自动代码编写,darknet中RNN算法学习》。是的,这是一篇关于人工智能算法的学习研究文章:) 通过RNN算法,用darknet程序分析过去我写过的程序,然后输入开头词,之后算法自动炮制出一段程序来。注意,这里的程序并不是从需求分析出发写出的,并不是软件工程意义上的程序,只是符合程序语法定义的一段文本。和网络上的那些机器自动写小说差不多的。
理论知识:各人工智能算法之间的关系
-
RNN Recurrent NN 时间序列相关,词序相关,适用于自然语言处理
-
CNN Convolutional NN 卷积,用于矩阵或者图像,不用特征提取
-
CRNN Convolutional + Recurrent
-
LSTM long-short term memory 优化了状态丢弃的部分
如下是折叠状态,没有时序
如下是时序状态(unfolder状态)
RNN是一个序列到序列的模型,假设xt−1,xt,xt+1是一个输入:“我是中国“,那么ot−1,ot就应该对应”是”,”中国”这两个,预测下一个词最有可能是什么?就是ot+1应该是”人”的概率比较大。RNN的最大优势在于,可以真正充分地利用所有上文信息来预测下一个词,而不像HMM那样,只能开一个n个词的窗口,只用前n个词来预测下一个词。所以RNN用来进行自动写作,拥有良好记忆能力,而HMM用于语音识别,窗口有限的场合。
实战操作:训练过程
./darknet rnn train cfg/rnn.train.cfg -file data.txt --这个data中不能有中文,所以我用纯程序文件
rnn.train.cfg中batch改为32, 否则报错cuda out of memory
-
1.首先把程序文件拷贝到data.txt (注意:在Ultraedit中用
%[ ^t]*[/][/]*^n
替换成^n
来过滤掉中文注释) -
2.运行训练,结果报错了,因为c文件中
Saving weights to /home/pjreddie/backup//rnn.backup
Couldn't open file: /home/pjreddie/backup//rnn.backup
-
3.在darknet中搜索pjreddie,全部改掉,重新编译(GPU=1)
-
4.运行命令如下:
./darknet rnn train cfg/rnn.train.cfg -file data.txt
-
5.训练成功,在backup目录下有weights,但是名字叫
rnn.backup
-
6.自动以package单词为开头写程序,命令
./darknet rnn generate cfg/rnn.cfg backup/zzzjava.weights -srand 0 -seed package -len 2000
package com.netease.bima.forensics.core.Util;
/**
* @author zhengzezhou
**/
@Controller
@RequestMapping(value = "/attestation", method = RequestMethod.POST)
public AttestationFileController(WebClient.Builder for you; it is
* strongly advised to inject it in your components and use it to create
* WebClient instances. Spring Boot is configuring that builder to share HTTP
* resources, reflect codecs setup in the same fashion as the server ones (see
* WebFlux HTTP codecs auto-configuration), and more.
* https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/Stryse;
import com.github.dockerjava.api.command.ExecCreateCmdResponse;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.ExecStartResultCallback;
import com.netease.bima.forensics.core.AttestationUtil;
import com.netease.bima.forensics.core.AttestationUtil;
import com.netease.bima.forensics.core.Util;
import com.netease.bima.forensics.process.model.DockerRequestDTO;
import com.netease.bima.forensics.core.AttestationFileController {
private static final int MAX_REFORMAT_WAIT_TIMES = 1000;
@Autowired
private String ak;
@Value("${app.need-reformat}")
private String ak;
@Value("${app.record-file-name}")
private String ak;
@Value("${app.attestation.ak}")
private String ak;
@Value("${app.record-file-name}")
private String ak;
@Value("${app.attestation.tmpDir}")
private String sk;
/**
* Spring Boot creates and pre-configures a WebClient.Builder webClientBuilder
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
log.info("ret of attestation(@Validated @RequestBody DockerRequestDTO;
嘿,还像模像样的!
对结果的具体分析
-
package用法位置对的,但是加上具体类就错误了。为什么?实际上这个位置的,是受前面几十个字符的影响
- 原文中package语句少,而import语句多,概率计算越大,也就是算法遗漏了package和import的区别
解决办法是1. LSTM 2.或者双向rnn 3.更大样本的学习
- 原文中package语句少,而import语句多,概率计算越大,也就是算法遗漏了package和import的区别
-
对/**/注释结构学习得很到位,因为这个
注释的边界非常清晰,而且没有嵌套
,但是另外一篇中,对行尾注释(无边界
)学习效果却是很差 darknet训练中cfg文件调参.md -
import是另外一个学习得比较好的,估计是样本量比较大,引用的各个类都是实际存在的,就是AttestationUtil被引用了两次。为什么?有趣的是,实际在原文中“core.AttestationUtil”只出现了一次
-
说明训练中肯定没有识别“不能重复出现”,因为原文中像core.Util之类的类就重复出现过
-
真要解决这个问题,程序文件毕竟不像小说,要改写darknet,支持多目录多文件,并且一次编写要以java文件方式完整出现
-
-
最关键的,为什么会出现混淆?见如下截图
- 原因显然是算法没有区分
类的定义
和constructor的定义
,原因还是1.样本太少 2.没有按目录结构来,不是小说啊
- 原因显然是算法没有区分
最终的目标是赋能静态代码检查,目前的findbugs之类还不够智能,就算发现了问题,提示也不够明确