C#_Markov_心得感想
来到实验室正好有一个月了,趁着端午假期稍微轻松一些,在大改程序体系之前,想将自己在这30天中工作之一Markov回顾一下,将从真实的写程序中学习到的知识、思想记录下来。希望能和大家积极讨论!
本文会以用C#实现Markov Model为主线,分享自己的感悟。
一、简介Markov
Markov是一种概率模型,最简单的理解是通过大量数据的学习后,可以通过个数为n的词推断出第n+1个词的出现可能。能理解Markov整体思想就可以了。
所以通常将Markov Model的实现分为两个部分:
1、Markov Model数据学习部分
2、根据Markov Model生成部分
二、Markov数据学习
很多人说,当Markov的阶数(Order)变高的时候,如order=5,数据学习部分根本跑不动,为什么?因为Markov要求的是全排列。举个例子,如果学习数据中有5000种词,阶数为5,那么我们有5000的5次方种全排列可能。在存储过程中,因为数据量过大,对内存的一种挑战;在搜索并累积的过程中,如果采用不适当的数据结构,将会消耗大量,超大量时间在搜索中。而这点也就是程序跑不动的原因。
功能的需求就只是个需求,怎么写程序根本是另一回事。很多程序不会按那个需求那么直接的实现,比如说我们现在要全排列,那我们就把全排列的结果全部都存在计算机中吗?我们做不到。我们得通过其他方法来实现这个需求,这就可能会稍微拐点弯啦,但能否灵巧地解决编程难点,看的就是不同程序员的能力高低了。
统计可以得到,全排列中有大量组合是没有值的,会是个稀疏矩阵。所以我只将学习数据中出现的词组合记录下来,这个数据量将远远小于应有的全排列,内存将会有足够的空间存放。在这样的前提下,我第一次使用的List做数据结构来存储,发现程序依然跑的很慢很慢,30mins才跑了50W数据;后来灵机一动用了Dictionary(hash)做数据结构,2mins就跑了300W数据……这真是天壤之别啊!!!这就说明数据结构真是太重要了!!!千万不要小看数据结构啊!!!一定要重视!!!以前学的时候只知道哈希查询效率是O(1),但从没有这么震撼的感触。
话又说回来,为什么Markov要求是全排列,像我这样只把出现的学习一样不可以吗?生成的时候只生成我们学到的内容不可以吗?不可以!因为Markov需要平滑,因为Markov需要考虑所有可能的情况,虽然没学习到的内容出现可能会非常低罢了!
既然有这样的需求,那我们依然需要稀疏矩阵中稀疏部分的值呀,所以我们在生成部分直接求呗,很快的。这也说明了一句古话,“逃得了初一,逃不过十五”,是在一开始我们就将所有稀疏部分的值求好呢,还是需要的时候临时再求呢?这有点像ECC和RSA,一个加密快一个解密快,那就合理使用嘛!服务器若需要做大量解密工作的话,就用RSA做公钥加密算法呗,因为解密快,就会少用点资源。要灵活地看程序真正使用场景的需求,是动态还是静态?是牺牲空间还是牺牲时间?哪有谁就比谁好呢?
这算是Markov学习数据过程中,最大的感触了,其他的就不说了。
三、根据Markov生成数据
这部分给我带来的最大的感触就是,代码要一定要和执行环境挂钩!不要想当然!一切要以程序真正实现为主!必须考虑计算机内存资源的合理分配!!!(这点大家可能都没有遇到过,就不和大家解释了)
为了能让程序正常运行,我们必须合理使用内存,内存的占用、内存的释放、一次使用多大的内存、用什么数据结构存放?我们都要去考虑!
长度太长的时候,内存经常到4个G,程序就报错了。在没有找到简单解决方案后,自己写了一个内存硬盘动态交换数据并支持断续执行的代码,而这个代码也是我非常想逼逼的哈哈。这个环节我直接上代码了,由于是代码片段,所以不是很好理解= =。
//通过循环来生成长度为0-maxlength的数据
for (int i = ; i < maxlength; i++)
{
//fragnum数决定着长度相同数据 “分存” 在几个txt中
//随着长度的增大数据数量会非常非常大
//故我们通过存储在多个txt中,可以保证txt文件的正常生成,可以做到 “分段” 跑数据!
int fragnum = ; for (int j = ; ; j++)
{
//读取Length为i,Part为j的文件,即长度为i的第j个存储数据的txt文件
string inpath = FileDirectory + "Markov_Length_" + i.ToString() + "_Part_" + j.ToString() + ".txt";
//ListofBase用来临时存放从上面文件中读取到的length-1的pre数据
//在循环内初始化List,可控制内存开销,保证可持续发展
List<string> ListofBase = new List<string>(); Console.WriteLine(i + " " + j); try
{
//将inpath文件中的basic数据读进ListofBase
StreamReader sr = new StreamReader(inpath, Encoding.Default);
String line;
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
ListofBase.Add(line); } Console.WriteLine("------------------------------"); //准备将生成的数据存储在长度为length为i+1的数据txt中
//part值由fragnum决定,fragnum在length层面上初始化为0,随后的值将一直伴随
string outpath = FileDirectory + "Markov_Length_" + (i + ).ToString() + "_Part_" + fragnum.ToString() + ".txt";
FileStream fs = new FileStream(outpath, FileMode.Create);
StreamWriter sw = new StreamWriter(fs); //modcount的大小决定从ListofBase中抽取多少个用来生成数据
//同一批数据生成的新数据存放在一个part中,用这个来具体实现对同一长度数据的 “碎片化” 存储
int modcount = ; //遍历整个ListofBase
foreach (var element in ListofBase)
{
//将modcount控制在(0,499999)之间
modcount = (modcount + ) % ; //若modcount等于499999,则说明foreach循环已经执行了500000次
//通过更改输出txt文件名来分开存储
if (modcount == )
{
//文件后续处理
sw.Flush();
sw.Close();
fs.Close(); //修改文件名,++fragnum
outpath = FileDirectory + "Markov_Length_" + (i + ).ToString() + "_Part_" + (++fragnum).ToString() + ".txt";
fs = new FileStream(outpath, FileMode.Create);
sw = new StreamWriter(fs);
} //temp用来存储ListofBase生成的数据
List<string> temp = new List<string>(); //调用ExtendPassword方法,element生成的数据存放在temp中
temp = ExtendPassword(element);
//并将temp中数据存放在文件中
foreach (var every in temp)
{
sw.WriteLine(every);
}
}
//文件后续处理
sw.Flush();
sw.Close();
fs.Close();
}
//如果没有读到(i,j)文件,那么判断Length为i的第j+1个部分是不存在的
//跳出循环,读Length为i+1,Part为0的txt文件
catch
{
break;
}
}
}
现在想想,那些安装程序、补丁程序、下载程序,关闭后还可以找到位置继续执行的功能是不是就是这段代码的特殊版?不过我也不知道那些程序是怎么写的,有机会能接触到就好啦。
不管是因为你自己要写,或是你的上级、你的客户下派了任务,还是出于其他原因,我们的重点都应该放在如何用计算机思维解决现实问题,应先了解计算机的功能,是串行计算还是并行计算?准备用过程性的编程思想还是面向对象的编程思想?既然要写程序,就要用你用的编程语言的思想、你的计算机的逻辑去解决这个问题。能将现实问题转换成巧妙的计算机程序这个能力,不是所有程序员都有的,一定要好好锻炼,路还很长,加油吧!
LIAN
大三下 2017/5/28
C#_Markov_心得感想的更多相关文章
- AI 系列 总目录
AI 系列 答应了园区大牛 张善友 要写AI 的系列博客,所以开始了AI 系列之旅. 一.四大平台系列(百度AI.阿里ET.腾讯.讯飞) 1.百度篇 (1) 百度OCR文字识别-身份证识别 (2) 基 ...
- 第6次结对作业--郑锦伟&古维城
第6次结对作业 在线英语学习平台客户端原型 1.结对成员 郑锦伟 2015034643034 古维城 2015034643033 2.原型设计工具实现-Photoshop 3.需求分析 使用NABCD ...
- 20165325 2017-2018-2《Java程序设计》课程总结
20165325 2017-2018-2<Java程序设计>课程总结 一.每周作业链接汇总 1.预备作业一:我期待的师生关系 20165325 期望的师生关系 简要内容: 我心中的好老师 ...
- 软件工程 BUAAMOOC项目Postmortem结果
设想和目标 1.我们的软件要解决什么问题?是否定义的很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件是基于北航MOOC网站做的Android手机客户端,用于便捷的在学校里通过手机做到随时随地 ...
- 20165320 2017-2018-2《Java程序设计》课程总结
20165320 2017-2017-2<Java程序设计>课程总结 一.每周作业链接汇总 1.我期待的师生关系 20165320 我期望的师生关系 2.学习基础和C语言基础调查 2016 ...
- Linux实验三
主要参考课本第二章所学习内容 (信息的表示和处理) 所有重点内容: 信息存储 整数表示/运算 浮点数 一 十六进制表示 0~9 A~F 0000~1111 注:(主要参考课本P22) 字 字长: ...
- PostgreSQL 优势,MySQL 数据库自身的特性并不十分丰富,触发器和存储过程的支持较弱,Greenplum、AWS 的 Redshift 等都是基于 PostgreSQL 开发的
PostgreSQL 优势 2016-10-20 21:36 686人阅读 评论(0) 收藏 举报 分类: MYSQL数据库(5) PostgreSQL 是一个自由的对象-关系数据库服务器(数据库 ...
- 我成为 Microsofti Azure MVP 啦!(ps:不是美国职业篮球)
一,引言 今天是个高兴的日子,早上10点左右收到了来自微软的MVP的礼包的快递,对我来说,这是一件很值得纪念的日子.所以今天就水一篇心得感想吧!!! 我是年前2月9号开始申请MVP的,经历了差不多1个 ...
- 获奖感想和python学习心得
一,获奖感想 很荣幸能成为小黄杉的获得者,也很感谢老师对我的这份鼓励和期望.回顾本学期的python学习中,我从一名对编程一无所知的小白,成为一名刚入门的程序猿.首先,我要感谢我的任课老师娄嘉鹏老师, ...
随机推荐
- Transformer-view java实体 转换视图 Lists.transform
自: https://blog.csdn.net/mnmlist/article/details/53870520 meta_ws 连接: https://github.com/kse-music/d ...
- codeforces 724c Ray Tracing
好题 原题: There are k sensors located in the rectangular room of size n × m meters. The i-th sensor is ...
- MySQL中UNSIGNED和ZEROFILL的介绍
UNSIGNED: 将数字类型无符号化,这与C和C++这些程序语言的unsigned含义相同. INT的类型范围-2 147 483 648~2 147 483 647 INT UNSIGNED范围0 ...
- hihocoder 1513 小Hi的烦恼——bitset
题目:http://hihocoder.com/problemset/problem/1513 自带的题解写得很好…… #include<cstdio> #include<cstri ...
- JZ2440 裸机驱动 第14章 ADC和触摸屏接口
本章目标: 了解S3C2410/S3C2440和触摸屏的结构: 了解电阻触摸屏的工作原理和等效电路图: 了解S3C2410/S3C2440触摸屏控制器的多种工作模式: ...
- ES(6): access elasticsearch via curl
curl是一个非常实用的.用来与服务器之间传输数据的工具:支持的协议包括 (DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, ...
- Densenet 相关
https://github.com/flyyufelix/DenseNet-Keras
- signal简述
一个几乎是最简单的应用如下: #include <unistd.h> // for alarm() #include <signal.h> // for signal() #i ...
- VS2010安装顽疾解决方法:error 25541 failed to open xml file
一.问题描述 因为之前(2012)对HDFS客户端Thrift接口的库文件封装使用的是VS2010,最近考虑做一个完整的网盘系统的客户端,就把该库文件使用起来,比较悲剧的是之前做过操作系统的还原.我的 ...
- java判断字符串中是否含有中文
/** * 判断字符串中是否含有中文 */ public static boolean isCNChar(String s){ boolean booleanValue = false; for(in ...