地球末日升级地板 1级森林2级森林怎么看

地球末日到来前的的第二大特征:城市扩大化_日出东方王一旭_新浪博客
地球末日到来前的的第二大特征:城市扩大化
我的专著《宇宙妈妈和地球女儿的对话》节选(写于2008年8月)
第二节:末日来临的第二个特征是城市扩大化
宇宙妈妈:地球末日到来的第二个特征是,城市的不断增多。
地球女儿:为什么城市增多也是末日的特征之一呢,妈妈?
宇宙妈妈:因为城市的增多就意味着水泥建筑的增多,人类为了交通的方便,就会不停的修路、建桥;人类为了居住的舒适,就会不停地盖着高楼大厦;人类为了生活的方便就会家家使用自来水,然后是天然气。
地球女儿:可是妈妈,您说的这一切不是人类发展的进步吗?
宇宙妈妈:我的女儿,一切事物都必须正反两面来看,从正的方面来看,这一切确实意味着人类的发展进步了,但是从反的方面来看,则意味着城市的增多,破坏自然界的事情就会增多,能够生长森林的地方则必然会减少。自来水用着越方便,人类浪费水的速度就会越快,交通越发达就意味着汽车工业越发达,人们出行的越方便,对汽油的消耗越多,对空气的污染越重,对道路的要求越高,修路的速度则越快。可是水泥道路修的越多,树就砍的越多,空气质量也会越差,雨水必然越少。这种恶性循环,导致人类向着死亡的道路上不停地迅跑,他们就像穿上了黑色的魔鞋,想停都停不了。
地球女儿:妈妈,将来人类世界的城市真的会很多吗?
宇宙妈妈:没错我的女儿,将来人类世界的城市化会形成一种潮流,许多曾经种庄稼的地方,都会变成高楼大厦,表面上看人类的每个城市都很漂亮,但是在这漂亮的背后,却暗藏着种种危机。
地球女儿:都会有什么样的危机呢,妈妈?
宇宙妈妈:首先是人与自然割裂的危机。由于城市中的水泥森林,越盖越多,人类和宇宙沟通联系的媒介——绿色森林则越来越少,而绿色森林少了,则意味着雨水越来越少。可是人类生活中的用水越来越方便,浪费水的行为则越来越多,这是一对无法调和的尖锐矛盾。
地球女儿:我明白了妈妈,因为人类不会下雨,他们只能靠天吃饭,而天空中的雨水则不喜欢降临到水泥多的地方对吗?
宇宙妈妈:说的对,好女儿。要知道水泥效应的力量是非常大的,许多带雨的云刚到城市的上空,就被水泥发向空中的力量给吸干了。所以,将来许多的大城市会感到雨水越来越少,城市越来越干渴。究其原因就是因为人类的行为与自然界完全割裂开来了。
地球女儿:其实自然界对人类的各种惩罚,实际上是人类自己对自己的惩罚对吗?
宇宙妈妈:确实如此,还是那句话,种什么因,结什么果。将来,即使人类有什么灭顶之灾,也无法怨天忧人,他们完全是昝由自取。
地球女儿:如果城市里的水都没有了,人类会采取什么办法来取生存之用的水呢,妈妈?
宇宙妈妈:他们会采取杀鸡取卵的办法,来索取水资源。
地球女儿:什么叫杀鸡取卵呢,妈妈?
宇宙妈妈:当大城市慢慢地多起来之后,他们确实面临着自然界对他们的嘲弄,天下的雨越来越少,地下水位下降的越来越快,人口增长的越来越多,需要喝水的人自然也就会越来越多。于是一些所谓的专家就开始出馊主意了。
地球女儿:这个比喻太有意思了,什么样的主意算是馊主意呢?
宇宙妈妈:这些所谓的专家,不是从城市大环境的绿色改善出发,而是舍近求远,要从几千公里以外的地方调水,这不是杀鸡取卵又是什么呢?
地球女儿:妈妈,几千公里外就会有水吗?如果人类真的这样做了,其结果会是什么呢?
宇宙妈妈:我的女儿,这个问题提的好,一般来讲,地球上每一个国家的南方受地理环境的影响,森林会比较多,因此下雨的机会也比较多,水资源相对北方来说要丰富一些。但是,人类不明白的是,地球上所有的山川河流几十亿年来,都形成了自己独特的气场,这种气场是不允许任何外来势力进行破坏的。一旦它们从结构上遭到了破坏,那么它们对人类的报复将是极其残酷的。
地球女儿:它们真的会报复人类吗?人类也真是的,难道他们真的不明白有树的地方就会风调雨顺吗?他们难道不能少盖一些楼,多种一些树来招唤雨神的降临吗?
宇宙妈妈:因为人们认为,盖房子可以立即赚到钱,而种树所得到的经济效益则时间太长,这就是人类的劣根性,不管自己子孙的死活,只想着自己如何享受。
地球女儿:于是他们就会舍近求远、于是他们就会劳民伤财、于是他们就会不顾大自然的痛苦感受、于是他们就会遭到自然界的残酷报复。我说的对吧,妈妈?
宇宙妈妈:正是如此。将来,一旦他们要施实这种工程的话,那么就会发生这样的情况,本来南方有水,可当人类要把南方的水引向北方的时候,南方突然大旱了。他们曾经丰盈的水,居然消失的无影无踪了,而那里的人民却会感受到干旱带来的可怕痛苦,
地球女儿:所以,认识宇宙智慧存在的必要性,已经成了人类最重要的获救之道,尊重自然界的一切,也将成为人类自救的最佳途径,天救自救者,这一点是任何时候都不能忘记的,对吗?
宇宙妈妈:说的好。
地球女儿:妈妈,看来人类如果不尽快认识到自己在宇宙中所处的位置,他们是不会懂得如何对待自然界的。他们可真是不合格的地球管理者呀。我很想知道,还有什么样的危机在等待着人类呢?
宇宙妈妈:当然还有能源的危机在等待他们了。
地球女儿:可是妈妈,水也是很重要的能源呀,它的危机咱们已经谈过了,还有什么样的能源危机呢?
宇宙妈妈:人类要想在这个世界上生活的很舒适,就需要各种各样能源的支持,水只是能源中的一种,但却是至关重要的一种。因为人可以不吃饭,但不能没有水。要知道人体中的水,占到了百分之七十哪。
地球女儿:城市中除了水的危机呢?
宇宙妈妈:还有电的危机。当地球上的科学发展到一定的程度时,人们对电的依赖就日趋加重了,他们照明需要电、看电视需要电、打电话需要电、用电脑需要电、开空调需要电、用冰箱需要电、洗澡需要电、楼盖高了坐电梯同样需要电、人们的生活富裕了,看电影也需要电、各种娱乐都需要电的支持。如果在农村,人们是不需要这么多电的,可是到了城市离开电,人类简直不知道如何生活了。
地球女儿:城市用电的地方这么多,可是电从哪里来呢,妈妈?
宇宙妈妈:人类在很长一段时间里,主要通过两种方式来发电。
地球女儿:是哪两种方式呢?
宇宙妈妈:一种是水利发电、另一种是火力发电。水利发电需要用大量的水,所以将来人类世界凡是有大江大河的地方,都会建立水利发电站。但是随着枯水的频率越来越多,这样的发电站则会越来越难以为继。
地球女儿:那火力发电呢,妈妈?
宇宙妈妈:火力发电更加浪费能源,因为火力发电需要用煤来支持,可是随着人口的不断增长,随着城市的不断增多,随着人类用电量的不断增强,可以用来发电的煤,却越来越少。因此,将来人类的各大城市都会出现拉闸限电的情况,而且这种情况还会越演越烈,最终会导致,每一个城市都会经常陷入一片漆黑之中。
地球女儿:难道人类不会考虑别的方式发电吗?
宇宙妈妈:后来人类还会建立一些核电站,但是它的后遗症太可怕了。
地球女儿:为什么这样说呢,妈妈?核电站有什么可怕的后遗症呢?
宇宙妈妈:那就是一旦这个核电站停止运转了,那它所留下的核废料,可以污染地球几百年,甚至几万年。而这种核污染还会导致人类患上各种各样的疾病。这难道不是可怕的后遗症吗?
地球女儿:既然人类知道有这么可怕的后果,为什么还要建立核电站呢?
宇宙妈妈:因为他们找不到更好的发电方式,在煤和水都日益枯竭之前,他们只能甘冒风险,满足人类的用电量。
地球女儿:我的天哪,人类的智慧在哪里?
宇宙妈妈:当然,他们也考虑利用太阳能。
地球女儿:太阳能?这很好呵,那可是取之不尽用之不竭的能源库呀,对不对?
宇宙妈妈:真的能用太阳能,当然好,但是人类只能在小的方面利用太阳能,在大的方面,他们做不到。
地球女儿:为什么呢,妈妈?
宇宙妈妈:因为城市已经成了水泥森林,根本没有地方安装大型的太阳能发电装置。
地球女儿:看来人类茫目建立大城市,真是害人害已呀。
宇宙妈妈:当人类进入了汽车工业快速发展之后,又面临着石油的危机了。于是尖锐的矛盾又出现了。一方面是人类为了方便舒适的生活,大力发展汽车工业,另一方面则是汽油的需求量大大增加,一方面是人类为了适应汽车的发展而修建大量的水泥公路,另一方面则是空气的污染程度在不断地加大。雾霾将成为所有城市的常态化,人们将无法呼吸了。
地球女儿:可想而知,石油的危机出现了,清新的空气没有了。这样算下来,人类至少有三大重要的能源出现了危机,对吗,妈妈?
宇宙妈妈:何止三种能源哪?其实随着人类城市化的不断加大,天燃气的需求也在不断加大,所以这种能源也一定会处于危机的边缘。
地球女儿:妈妈,我想问您一个问题。
宇宙妈妈:什么问题呢,我的女儿?
地球女儿:我真的很想知道,人类爱自己的孩子吗?
宇宙妈妈:当然。
地球女儿:可是妈妈,听了您讲的这一切,我对此表示极度的怀疑。我觉得,人类非但不爱自己的孩子,反而很恨自己的孩子,否则他们怎么能如此发展自己的世界呢?
宇宙妈妈:说的好,我亲爱的女儿。人类对自己孩子的爱是短视的,是畸形的,他们只知道让自己的孩子拼命吃好的、穿好的、用好的、再逼迫孩子拼命地学东学西,升学升学再升学,却不知道为了孩子的未来节约水、节约电、节约一切可以节约的能源,让孩子成为一个热爱自然界的人。
地球女儿:我也看出来了,妈妈。人类杀光了自己的兄弟——野生动物们,让自己的孩子从小就失去许多优秀的老师;他们砍光了地球上的森林,让自己的孩子从小就生活在水泥森林中;他们拼命地浪费着地球上的一切能源,让自己的孩子从小就处于各种能源缺失的危机之中;他们不知道如何关爱自己的孩子,让我觉得人类实在又可恨,又可怜。
宇宙妈妈:除了前面所讲的那几个末日来临的特征之外,还有一个特征是必须要讲的。
地球女儿:是什么样的特征呢,妈妈?
宇宙妈妈:这个特征就是,人类为了战争而制造的核武器,已经严重地威胁到了整个地球的安全。如果不及时地清除掉这些核武器,那么人类很可能自己制造一个地球末日的到来,所以,你要记住这个末日的特征。
地球女儿:妈妈,我觉得这个特征最危险,因为它不象能源的危机那样,有一段时间的缓冲。可是核武器不一样,它随时随地都可能暴发,如果掌握它的人,是一个道德水平低下的人,我说的对吗?
宇宙妈妈:完全正确,我的女儿。将来,地球世界会有许多国家研制了核武器,其中只有美国真正使用过了核武器。
地球女儿:真的吗?那岂不是太可怕了吗?他们使用核武器的结果是什么呢,妈妈?
宇宙妈妈:前面我们谈到过第二次世界大战,正是在那场战争中,美国将刚刚研制出的核武器,扔到了日本的广岛和长崎,结果毁灭性地重创了这两个城市,而核武器造成的辐射,让这两个城市的无数人,忍受了几十年的痛苦。幸亏他们研制的核武器威力还不算大。
地球女儿:天哪,妈妈。一下子毁了两座城市,威力还不大呀。
宇宙妈妈:后来人类研制的核武器,其威力能够毁灭几十个地球。
地球女儿:真不明白人类究竟想干什么?他们到底是希望自己生活安乐幸福呢?还是希望自己尽快毁灭呢?
日出东方王一旭
博客等级:
博客积分:0
博客访问:3,160,896
关注人气:0
荣誉徽章:1.随机森林原理介绍
随机森林,指的是利用多棵树对样本进行训练并预测的一种分类器。该分类器最早由Leo Breiman和Adele Cutler提出,并被注册成了商标。简单来说,随机森林就是由多棵CART(Classification And Regression Tree)构成的。对于每棵树,它们使用的训练集是从总的训练集中有放回采样出来的,这意味着,总的训练集中的有些样本可能多次出现在一棵树的训练集中,也可能从未出现在一棵树的训练集中。在训练每棵树的节点时,使用的特征是从所有特征中按照一定比例随机地无放回的抽取的,根据Leo Breiman的建议,假设总的特征数量为M,这个比例可以是sqrt(M),1/2sqrt(M),2sqrt(M)。
因此,随机森林的训练过程可以总结如下:
(1)给定训练集S,测试集T,特征维数F。确定参数:使用到的CART的数量t,每棵树的深度d,每个节点使用到的特征数量f,终止条件:节点上最少样本数s,节点上最少的信息增益m
对于第1-t棵树,i=1-t:
(2)从S中有放回的抽取大小和S一样的训练集S(i),作为根节点的样本,从根节点开始训练
(3)如果当前节点上达到终止条件,则设置当前节点为叶子节点,如果是分类问题,该叶子节点的预测输出为当前节点样本集合中数量最多的那一类c(j),概率p为c(j)占当前样本集的比例;如果是回归问题,预测输出为当前节点样本集各个样本值的平均值。然后继续训练其他节点。如果当前节点没有达到终止条件,则从F维特征中无放回的随机选取f维特征。利用这f维特征,寻找分类效果最好的一维特征k及其阈值th,当前节点上样本第k维特征小于th的样本被划分到左节点,其余的被划分到右节点。继续训练其他节点。有关分类效果的评判标准在后面会讲。
(4)重复(2)(3)直到所有节点都训练过了或者被标记为叶子节点。
(5)重复(2),(3),(4)直到所有CART都被训练过。
利用随机森林的预测过程如下:
对于第1-t棵树,i=1-t:
(1)从当前树的根节点开始,根据当前节点的阈值th,判断是进入左节点(&th)还是进入右节点(&=th),直到到达,某个叶子节点,并输出预测值。
(2)重复执行(1)直到所有t棵树都输出了预测值。如果是分类问题,则输出为所有树中预测概率总和最大的那一个类,即对每个c(j)的p进行累计;如果是回归问题,则输出为所有树的输出的平均值。
注:有关分类效果的评判标准,因为使用的是CART,因此使用的也是CART的评判标准,和C3.0,C4.5都不相同。
对于分类问题(将某个样本划分到某一类),也就是离散变量问题,CART使用Gini值作为评判标准。定义为Gini=1-&(P(i)*P(i)),P(i)为当前节点上数据集中第i类样本的比例。例如:分为2类,当前节点上有100个样本,属于第一类的样本有70个,属于第二类的样本有30个,则Gini=1-0.7&07-0.3&03=0.42,可以看出,类别分布越平均,Gini值越大,类分布越不均匀,Gini值越小。在寻找最佳的分类特征和阈值时,评判标准为:argmax(Gini-GiniLeft-GiniRight),即寻找最佳的特征f和阈值th,使得当前节点的Gini值减去左子节点的Gini和右子节点的Gini值最大。
对于回归问题,相对更加简单,直接使用argmax(Var-VarLeft-VarRight)作为评判标准,即当前节点训练集的方差Var减去减去左子节点的方差VarLeft和右子节点的方差VarRight值最大。
2.OpenCV函数使用
OpenCV提供了随机森林的相关类和函数。具体使用方法如下:
(1)首先利用CvRTParams定义自己的参数,其格式如下
CvRTParams::CvRTParams(int max_depth, int min_sample_count, float regression_accuracy, bool use_surrogates, int max_categories, const float* priors, bool calc_var_importance, int nactive_vars, int max_num_of_trees_in_the_forest, float forest_accuracy, int termcrit_type)
大部分参数描述都在http://docs.opencv.org/modules/ml/doc/random_trees.html上面有,说一下没有描述的几个参数的意义
bool&use_surrogates:是否使用代理,指的是,如果当前的测试样本缺少某些特征,但是在当前节点上的分类or回归特征正是缺少的这个特征,那么这个样本就没法继续沿着树向下走了,达不到叶子节点的话,就没有预测输出,这种情况下,可以利用当前节点下面的所有子节点中的叶子节点预测输出的平均值,作为这个样本的预测输出。
const float*priors:先验知识,这个指的是,可以根据各个类别样本数量的先验分布,对其进行加权。比如:如果一共有3类,第一类样本占整个训练集的80%,其余两类各占10%,那么这个数据集里面的数据就很不平均,如果每类的样本都加权的话,就算把所有样本都预测成第一类,那么准确率也有80%,这显然是不合理的,因此我们需要提高后两类的权重,使得后两类的分类正确率也不会太低。
float&regression_accuracy:回归树的终止条件,如果当前节点上所有样本的真实值和预测值之间的差小于这个数值时,停止生产这个节点,并将其作为叶子节点。
后来发现这些参数在决策树里面有解释,英文说明在这里http://docs.opencv.org/modules/ml/doc/decision_trees.html#cvdtreeparams
具体例子如下,网上找了个别人的例子,自己改成了可以读取MNIST数据并且做分类的形式,如下:
#include &cv.h&
// opencv general include file
#include &ml.h&
// opencv machine learning include file
#include &stdio.h&
using namespace // OpenCV API is in the C++ "cv" namespace
/******************************************************************************/
// global definitions (for speed and ease of use)
//手写体数字识别
#define NUMBER_OF_TRAINING_SAMPLES 60000
#define ATTRIBUTES_PER_SAMPLE 784
#define NUMBER_OF_TESTING_SAMPLES 10000
#define NUMBER_OF_CLASSES 10
// N.B. classes are integer handwritten digits in range 0-9
/******************************************************************************/
// loads the sample database from file (which is a CSV text file)
inline void revertInt(int&x)
x=((x&0x000000ff)&&24)|((x&0x0000ff00)&&8)|((x&0x00ff0000)&&8)|((x&0xff000000)&&24);
int read_data_from_csv(const char* samplePath,const char* labelPath, Mat data, Mat classes,
int n_samples )
FILE* sampleFile=fopen(samplePath,"rb");
FILE* labelFile=fopen(labelPath,"rb");
int mbs=0,number=0,col=0,row=0;
fread(&mbs,4,1,sampleFile);
fread(&number,4,1,sampleFile);
fread(&row,4,1,sampleFile);
fread(&col,4,1,sampleFile);
revertInt(mbs);
revertInt(number);
revertInt(row);
revertInt(col);
fread(&mbs,4,1,labelFile);
fread(&number,4,1,labelFile);
revertInt(mbs);
revertInt(number);
unsigned char
for(int line = 0; line & n_ line++)
// for each attribute on the line in the file
for(int attribute = 0; attribute & (ATTRIBUTES_PER_SAMPLE + 1); attribute++)
if (attribute & ATTRIBUTES_PER_SAMPLE)
// first 64 elements (0-63) in each line are the attributes
fread(&temp,1,1,sampleFile);
//fscanf(f, "%f,", &tmp);
data.at&float&(line, attribute) = static_cast&float&(temp);
// printf("%f,", data.at&float&(line, attribute));
else if (attribute == ATTRIBUTES_PER_SAMPLE)
// attribute 65 is the class label {0 ... 9}
fread(&temp,1,1,labelFile);
//fscanf(f, "%f,", &tmp);
classes.at&float&(line, 0) = static_cast&float&(temp);
// printf("%f\n", classes.at&float&(line, 0));
fclose(sampleFile);
fclose(labelFile);
return 1; // all OK
/******************************************************************************/
int main( int argc, char** argv )
for (int i=0; i& i++)
std::cout&&argv[i]&&std::
// lets just check the version first
printf ("OpenCV version %s (%d.%d.%d)\n",
CV_VERSION,
CV_MAJOR_VERSION, CV_MINOR_VERSION, CV_SUBMINOR_VERSION);
//定义训练数据与标签矩阵
Mat training_data = Mat(NUMBER_OF_TRAINING_SAMPLES, ATTRIBUTES_PER_SAMPLE, CV_32FC1);
Mat training_classifications = Mat(NUMBER_OF_TRAINING_SAMPLES, 1, CV_32FC1);
//定义测试数据矩阵与标签
Mat testing_data = Mat(NUMBER_OF_TESTING_SAMPLES, ATTRIBUTES_PER_SAMPLE, CV_32FC1);
Mat testing_classifications = Mat(NUMBER_OF_TESTING_SAMPLES, 1, CV_32FC1);
// define all the attributes as numerical
// alternatives are CV_VAR_CATEGORICAL or CV_VAR_ORDERED(=CV_VAR_NUMERICAL)
// that can be assigned on a per attribute basis
Mat var_type = Mat(ATTRIBUTES_PER_SAMPLE + 1, 1, CV_8U );
var_type.setTo(Scalar(CV_VAR_NUMERICAL) ); // all inputs are numerical
// this is a classification problem (i.e. predict a discrete number of class
// outputs) so reset the last (+1) output var_type element to CV_VAR_CATEGORICAL
var_type.at&uchar&(ATTRIBUTES_PER_SAMPLE, 0) = CV_VAR_CATEGORICAL;
double // value returned from a prediction
//加载训练数据集和测试数据集
if (read_data_from_csv(argv[1],argv[2], training_data, training_classifications, NUMBER_OF_TRAINING_SAMPLES) &&
read_data_from_csv(argv[3],argv[4], testing_data, testing_classifications, NUMBER_OF_TESTING_SAMPLES))
/********************************步骤1:定义初始化Random Trees的参数******************************/
float priors[] = {1,1,1,1,1,1,1,1,1,1};
// weights of each classification for classes
CvRTParams params = CvRTParams(20, // max depth
50, // min sample count
0, // regression accuracy: N/A here
false, // compute surrogate split, no missing data
15, // max number of categories (use sub-optimal algorithm for larger numbers)
priors, // the array of priors
// calculate variable importance
// number of variables randomly selected at node and used to find the best split(s).
// max number of trees in the forest
// forest accuracy
CV_TERMCRIT_ITER |
CV_TERMCRIT_EPS // termination cirteria
/****************************步骤2:训练 Random Decision Forest(RDF)分类器*********************/
printf( "\nUsing training database: %s\n\n", argv[1]);
CvRTrees* rtree = new CvRT
bool train_result=rtree-&train(training_data, CV_ROW_SAMPLE, training_classifications,
Mat(), Mat(), var_type, Mat(), params);
float train_error=rtree-&get_train_error();
printf("train error:%f\n",train_error);
// perform classifier testing and report results
int correct_class = 0;
int wrong_class = 0;
int false_positives [NUMBER_OF_CLASSES] = {0,0,0,0,0,0,0,0,0,0};
printf( "\nUsing testing database: %s\n\n", argv[2]);
for (int tsample = 0; tsample & NUMBER_OF_TESTING_SAMPLES; tsample++)
// extract a row from the testing matrix
test_sample = testing_data.row(tsample);
/********************************步骤3:预测*********************************************/
result = rtree-&predict(test_sample, Mat());
printf("Testing Sample %i -& class result (digit %d)\n", tsample, (int) result);
// if the prediction and the (true) testing classification are the same
// (N.B. openCV uses a floating point decision tree implementation!)
if (fabs(result - testing_classifications.at&float&(tsample, 0))
&= FLT_EPSILON)
// if they differ more than floating point error =& wrong class
wrong_class++;
false_positives[(int) result]++;
// otherwise correct
correct_class++;
printf( "\nResults on the testing database: %s\n"
"\tCorrect classification: %d (%g%%)\n"
"\tWrong classifications: %d (%g%%)\n",
correct_class, (double) correct_class*100/NUMBER_OF_TESTING_SAMPLES,
wrong_class, (double) wrong_class*100/NUMBER_OF_TESTING_SAMPLES);
for (int i = 0; i & NUMBER_OF_CLASSES; i++)
printf( "\tClass (digit %d) false postives
%d (%g%%)\n", i,
false_positives[i],
(double) false_positives[i]*100/NUMBER_OF_TESTING_SAMPLES);
// all matrix memory free by destructors
// all OK : main returns 0
// not OK : main returns -1
return -1;
MNIST样本可以在这个网址/exdb/mnist/下载,改一下路径可以直接跑的。
3.如何自己设计随机森林程序
有时现有的库无法满足要求,就需要自己设计一个分类器算法,这部分讲一下如何设计自己的随机森林分类器,代码实现就不贴了,因为在工作中用到了,因此比较敏感。
首先,要有一个RandomForest类,里面保存整个树需要的一些参数,包括但不限于:训练样本数量、测试样本数量、特征维数、每个节点随机提取的特征维数、CART树的数量、树的最大深度、类别数量(如果是分类问题)、一些终止条件、指向所有树的指针,指向训练集和测试集的指针,指向训练集label的指针等。还要有一些函数,至少要有train和predict吧。train里面直接调用每棵树的train方法即可,predict同理,但要对每棵树的预测输出做处理,得到森林的预测输出。
其次,要有一个sample类,这个类可不是用来存储训练集和对应label的,这是因为,每棵树、每个节点都有自己的样本集和,如果你的存储每个样本集和的话,需要的内存实在是太过巨大了,假设样本数量为M,特征维数为N,则整个训练集大小为M&N,而每棵树的每层都有这么多样本,树的深度为D,共有S棵树的话,则需要存储M&N&D&S的存储空间。这实在是太大了。因此,每个节点训练时用到的训练样本和特征,我们都用序号数组来代替,sample类就是干这个的。sample的函数基本需要两个就行,第一个是从现有训练集有放回的随机抽取一个新的训练集,当然,只包含样本的序号。第二个函数是从现有的特征中无放回的随机抽取一定数量的特征,同理,也是特征序号即可。
然后,需要一个Tree类,代表每棵树,里面保存树的一些参数以及一个指向所有节点的指针。
最后,需要一个Node类,代表树的每个节点。
需要说明的是,保存树的方式可以是最普通的数组,也可是是vector。Node的保存方式同理,但是个人不建议用链表的方式,在程序设计以及函数处理上太麻烦,但是在省空间上并没有太多的体现。
目前先写这么多,最后这部分我还会再扩充一些。
在github上开源了一个简单的随机森林程序,包含训练、预测部分,支持分类和回归问题,里面有mnist训练的实例,附了不少注释,比较适合入门学习,地址:
/handspeaker/RandomForests
阅读(...) 评论()

我要回帖

更多关于 地球末日地板怎么升级 的文章

 

随机推荐