随机森林的特征 是放回抽样么_机器学习超详细实践攻略(10):随机森林算法详解及小白都能看懂的调参指南...

82437919064ddeee16b19ee1f01402e3.png

一、什么是随机森林

前面我们已经介绍了决策树的基本原理和使用。但是决策树有一个很大的缺陷:因为决策树会非常细致地划分样本,如果决策树分得太多细致,会导致其在训练集上出现过拟合,而如果决策树粗略地划分样本,又不能很好地拟合样本。

为了解决这个两难困境,聪明的专家们想出了这样的思路:既然我增加单棵树的深度会适得其反,那不如我不追求一个树有多高的精确度,而是训练多棵这样的树来一块预测,一棵树的力量再大,也是有限的,当他们聚成一个集体,它的力量可能是难以想象的,也就是我们常说的:“三个臭皮匠赛过诸葛亮”。这便是集成学习的思想。

这里多提一句,正是因为每棵树都能够用比较简单的方法细致地拟合样本,我们可以多用几棵树来搭建准确率更高的算法,后边要说到的一些工业级的算法,比如GBDT、XGBOOST、LGBM都是以决策树为积木搭建出来的。

所以在学习这些算法的过程中,我们也要把决策树算法看成一块块积木,学完了基本的积木算法之后,对于现在常用的那几个工业级的算法,只需要理清两个问题:

1)这个算法利用了哪个集成学习思想

2)这个算法具体怎么把这个思想实现出来的。

随机森林就是决策树们基于bagging集成学习思想搭建起来的。

随机森林的算法实现思路非常简单,只需要记住一句口诀:抽等量样本,选几个特征,构建多棵树。

下面,我们详细解释这个口诀的含义:

1)抽等量样本

随机森林训练每棵树之前,都会从训练集中随机抽出一部分样本来训练。所以说训练每棵树用到的样本其实都是有差别的,这样就保证了不同的树可以重点学习不同的样本。而为了达到抽等量样本的目的,抽样方式一般是有放回的抽样,也就是说,在训练某棵树的时候,这一次被抽到的样本会被放回数据集中,下一次还可能被抽到,因此,原训练集中有的样本会多次被抽出用来训练,而有的样本可能不会被使用到。

但是不用担心有的样本没有用到,只要训练的树的棵数足够多,大多数训练样本总会被取到的。有极少量的样本成为漏网之鱼也不用担心,后边我们会筛选他们出来用来测试模型。

2)选几个特征

在训练某棵树的时候,也不是将样本的所有特征都用来训练,而是会随机选择一部分特征用来训练。这样做的目的就是让不同的树重点关注不同的特征。在scikit-learn中,用“max_features”这个参数来控制训练每棵树选取的样本数。

3)构建多棵树。

通过1)、2)两个步骤,训练多棵树。鲁迅曾经说过:世界上本没有森林,长得树多了,就成了森林。正是一棵棵决策树构成了整个随机森林。具体构建树的数量,在scikit-learn中,用“n_estimators”这个参数来控制。

197444d4549011d18b95e4630186f316.png

那最终的预测结果怎么得到呢?随机森林是非常民主的算法,最终的结果由每棵决策树综合给出:如果是分类问题,那么对于每个测试集,树都会预测出一个类别进行投票,最终统计票数多的那个类别为最终类别。看看,这算法俨然是一个遵循:“少数服从多数”的原则的小型民主社会;如果是回归问题,那就更简单了,各个树得到的结果相加求得一个平均值为最终回归结果。

从上边的流程中可以看出,随机森林的随机性主要体现在两个方面:数据集的随机选取、每棵树所使用特征的随机选取。以上两个随机性使得随机森林中的决策树都能够彼此不同,提升系统的多样性,从而提升分类性能。

二、随机森林的特点

以上就是随机森林的构建原理,下面,我们说说随机森林算法的优缺点:

1、优点:

1)实现简单,泛化能力强,可以并行实现,因为训练时树与树之间是相互独立的;

2)相比单一决策树,能学习到特征之间的相互影响,且不容易过拟合;

3)能直接特征很多的高维数据,因为在训练过程中依旧会从这些特征中随机选取部分特征用来训练;

4)相比SVM,不是很怕特征缺失,因为待选特征也是随机选取;

5)训练完成后可以给出特征重要性。当然,这个优点主要来源于决策树。因为决策树在训练过程中会计算熵或者是基尼系数,越往树的根部,特征越重要。

2、缺点

1)在噪声过大的分类和处理回归问题时还是容易过拟合;

2)相比于单一决策树,它的随机性让我们难以对模型进行解释。

三、随机森林的使用

和决策树类似,随机森林同样可以分为分类森林(RandomForestClassifier )和回归森林(RandomForestRegressor),在scikit-lean中调用方式和决策树相同。

让我们在手写识别数据集上实现一个分类森林。

#导入必要的包
from sklearn.ensemble import RandomForestClassifier 
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split,GridSearchCV,cross_val_score
from sklearn.metrics import accuracy_score
import matplotlib.pyplot as plt
import numpy as np#导入数据集
data = load_digits()
x = data.data
y = data.target

用随机森林训练并进行交叉验证:

RF = RandomForestClassifier(random_state = 66)
score = cross_val_score(RF,x,y,cv=10).mean()
print('交叉验证得分: %.4f'%score)

输出:

交叉验证得分: 0.9278

四、随机森林调参

一)随机森林参数介绍

除了和决策树有的参数之外,对于随机森林,只需要掌握8个新增的参数即可,我将这8个参数分成三类:

1、用于调参的参数:

  • max_features(最大特征数): 这个参数用来训练每棵树时需要考虑的最大特征个数,超过限制个数的特征都会被舍弃,默认为auto。可填入的值有:int值,float(特征总数目的百分比),“auto”/“sqrt”(总特征个数开平方取整),“log2”(总特征个数取对数取整)。默认值为总特征个数开平方取整。值得一提的是,这个参数在决策树中也有但是不重要,因为其默认为None,即有多少特征用多少特征。为什么要设置这样一个参数呢?原因如下:考虑到训练模型会产生多棵树,如果在训练每棵树的时候都用到所有特征,以来导致运算量加大,二来每棵树训练出来也可能千篇一律,没有太多侧重,所以,设置这个参数,使训练每棵树的时候只随机用到部分特征,在减少整体运算的同时还可以让每棵树更注重自己选到的特征。
  • n_estimators:随机森林生成树的个数,默认为100。

2、控制样本抽样参数:

  • bootstrap:每次构建树是不是采用有放回样本的方式(bootstrap samples)抽取数据集。可选参数:True和False,默认为True。
  • oob_score:是否使用袋外数据来评估模型,默认为False。

boostrap和 oob_score两个参数一般要配合使用。如果boostrap是False,那么每次训练时都用整个数据集训练,如果boostrap是True,那么就会产生袋外数据。

先解释一下袋外数据的概念:

在一个含有n个样本的原始训练集中,我们每次随机取出一个样本并记录,并在抽取下一个样本之前将该样本放回原始训练集,即下次采样时这个样本依然可能被采集到,这样采集n次,最终得到一个和原始训练集一样大的子数据集。

由于是随机采样,这样每次的子数据集和原始数据集都不同,用这些子数据集来各自训练一棵树,这些树的参数自然也就各不相同了。

然而有放回抽样也会有自己的问题。由于是有放回,一些样本可能在同一个自助集中出现多次,而其他一些却可能被忽略,一般来说,每一次抽样,某个样本被抽到的概率是 1/n ,所以不被抽到的概率就是 1-1/n ,所以n个样本都不被抽到的概率就是:

用洛必达法则化简,可以得到这个概率收敛于(1/e),约等于0.37。

因此,如果数据量足够大的时候,会有约37%的训练数据被浪费掉,没有参与建模,这些数据被称为袋外数据(out of bag data,简写为oob)。

为了这些数据不被浪费,我们也可以把他们用来作为集成算法的测试集。也就是说,在使用随机森林时,我们可以不划分测试集和训练集,只需要用袋外数据来测试我们的模型即可。

当然,这需要样本数据n和分类器个数n_estimators都很大,如果数据集过少,很可能就没有数据掉落在袋外,自然也就无法使用oob数据来测试模型了。

当bootstrap参数取默认值True时,表示抽取数据集时采用这种有放回的随机抽样技术。如果希望用袋外数据来测试,则需要在实例化时就将oob_score这个参数调整为True,训练完毕之后,我们可以用随机森林的另一个重要属性:oob_score_来查看我们的在袋外数据上测试的结果,代码如下:

#训练一个模型,让oob_score=True
输出:0.9393433500278241

这个就是没有参与训练的数据集在模型上的测试得分。

3、不重要参数

  • max_samples:构建每棵树需要抽取的最大样本数据量,默认为None,即每次抽取样本数量和原数据量相同。
  • n_jobs::设定fit和predict阶段并列执行的CPU核数,如果设置为-1表示并行执行的任务数等于计算机核数。默认为None,即采用单核计算。
  • verbose:控制构建数过程的冗长度,默认为0。一般不需要管这个参数。
  • warm_start:当设置为True,重新使用之前的结构去拟合样例并且加入更多的估计器(estimators,在这里就是随机树)到组合器中。默认为 False

以上这几个参数只需要简单了解即可,大多数参数在使用过称重不用调整,只是需要注意一点,n_jobs默认为None,为了加快速度,可以把n_jobs设置为-1。

二)随机森林调参顺序

介绍完了这些参数,接下来就要介绍随机森林的调参顺序了,随机森林的调参顺序一般遵循先重要后次要、先粗放后精细的原则,即先确定需要多少棵树参与建模,再对每棵树做细致的调参,精益求精。

相对于xgboost等算法,随机森林的调参还是相对比较简单,因为各个参数之间互相影响的程度很小,只需要按步骤调整即可。

结合我们决策树文章中提到的参数以及今天所讲的两个参数,随机森林中主要用来调参的参数有6个:

  • n_estimators:
  • criterion
  • max_depth
  • min_samples_split
  • min_samples_leaf
  • max_features

调参顺序如下:

1)选择criterion参数(决策树划分标准)

和决策树一样,这个参数只有两个参数 'entropy'(熵) 和 'gini'(基尼系数)可选,默认为gini,这里简单测试一下就好

RF = RandomForestClassifier(random_state = 66)
score = cross_val_score(RF,x,y,cv=10).mean()
print('基尼系数得分: %.4f'%score)
RF = RandomForestClassifier(criterion = 'entropy',random_state = 66)
score = cross_val_score(RF,x,y,cv=10).mean()
print('熵得分: %.4f'%score)

输出:

基尼系数得分: 0.9278
熵得分: 0.9249

这里看到,依旧是选用gini系数模型效果更好。

2)探索n_estimators的最佳值。

接下来才是进入真正的调参环节。根据上述调参原则,我们先看看用几棵树模型的表现最好。一般来说,树的棵数越多,模型效果表现越好,但树的棵数达到一定的数量之后,模型精确度不再上升,训练这个模型的计算量却逐渐变大。这个时候,再加树的数量就没必要了。就好比你饿的时候每吃一个馒头就特别顶饱,但是吃到一定数量的馒头之后,再吃就要撑着了。

只要找到这个临界值,这个参数就调好了。为了观察得分随着树增多的变化,我们依然绘制决策树调参时的学习曲线。

###调n_estimators参数
ScoreAll = []
for i in range(10,200,10):DT = RandomForestClassifier(n_estimators = i,random_state = 66) #,criterion = 'entropy'score = cross_val_score(DT,data.data,data.target,cv=10).mean()ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

输出:

最优参数以及最高得分: [120. 0.95560035]

fcb547239e3d2ec7836df831f2d7aa7b.png
调n_estimators参数

根据曲线,我们进一步缩小范围,搜索100~130之间的得分。(这里可以根据经验自己指定)

###进一步缩小范围,调n_estimators参数
ScoreAll = []
for i in range(100,130):DT = RandomForestClassifier(n_estimators = i,random_state = 66)   #criterion = 'entropy',score = cross_val_score(DT,data.data,data.target,cv=10).mean()ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

输出:

最优参数以及最高得分: [117. 0.95727946]

e792712c663f85dbe34d4af1135599e0.png
调n_estimators参数


可以看到,117为得分最高点,我们暂定n_estimators为117,接着调下边的参数。

3)探索max_depth(树的最大深度)最佳参数

###粗调max_depth参数
ScoreAll = []
for i in range(10,30,3):DT = RandomForestClassifier(n_estimators = 117,random_state = 66,max_depth =i ) #,criterion = 'entropy'score = cross_val_score(DT,data.data,data.target,cv=10).mean()ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

输出:

最优参数以及最高得分: [16. 0.95727946]

b6fb6e3478b30250bc0d9c0eab9482d1.png
max_depth参数

转折点在16,但是16之后一直没有变化,可以说明就算不限制,所有树的最大深度也就是16左右,因为我们以步长为3搜索的,所以还需要进一步搜索一下16附近的值。

精细搜索之后发现,16这个值就是转折点,所以暂定max_depth = 16。

4)探索min_samples_split(分割内部节点所需的最小样本数)最佳参数
min_samples_split最小值就是2,我们就从2开始调起。

###调min_samples_split参数
ScoreAll = []
for i in range(2,10):RF = RandomForestClassifier(n_estimators = 117,random_state = 66,max_depth =16,min_samples_split = i ) #,criterion = 'entropy'score = cross_val_score(RF,data.data,data.target,cv=10).mean()ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

输出:

最优参数以及最高得分: [2. 0.95727946]

9fadff71cd149e4b25066863842ccb52.png
min_samples_split参数


可以看到,随着min_samples_split增大,模型得分下降,说明没有出现过拟合现象,min_samples_split暂定2。

5)探索min_samples_leaf(分割内部节点所需的最小样本数)最佳参数

###调min_samples_leaf参数
ScoreAll = []
for i in range(1,15,2):DT = RandomForestClassifier(n_estimators = 117,random_state = 66,max_depth =16,min_samples_leaf = i,min_samples_split = 2 ) score = cross_val_score(DT,data.data,data.target,cv=10).mean()ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] ##这句话看似很长的,其实就是找出最高得分对应的索引
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

输出:

最优参数以及最高得分: [1. 0.95727946]

5ad01980c068d83e8244149f35734f91.png
min_samples_leaf参数

5)对每棵树用到的最大特征数max_features调参:

正常来说,只要这个值不要设置得太小,所有特征都会被整个森林抽取到用来训练, 所以相对来说这个值对整个模型的影响不是太大。但这个值越大,单棵树需要考虑的特征越多,虽然模型的表现可能会更好,但是增加这个值会导致算法运行速度变慢,所以需要我们考虑去找一个平衡值。

#调max_features参数
param_grid = {'max_features':np.arange(0.1, 1)}rfc = RandomForestClassifier(random_state=66,n_estimators = 117,max_depth = 16,min_samples_leaf =1 ,min_samples_split =4 )
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
print(GS.best_params_)
print(GS.best_score_)

输出:

{'max_features': 0.1}
0.9560335195530726

如果时间充裕,接下来也可以将min_samples_leaf和min_samples_split作为网格参数联调一下,因为这两个参数会相互影响,这里暂时省略这一步。

此时,我们得到的参数如下:

参数值n_estimators117max_depth16min_samples_leaf1min_samples_split2max_features0.1

6)在得到的最优参数附近进行小范围网格搜索

因为手动调参时,这些参数可能会相互影响,导致我们得到的参数还不是最优的。所以在最优参数附近进行小范围的网格搜索,排出相互影响的因素,尤其是在数据集量比较少时,小范围搜索一下可能会有意外收获。

import time
start = time.time()param_grid = {'n_estimators':np.arange(140, 150),'max_depth':np.arange(15, 18),'min_samples_leaf':np.arange(1, 8),'min_samples_split':np.arange(2, 5),'max_features':np.arange(0.1, 1)
}rfc = RandomForestClassifier(random_state=66)
GS = GridSearchCV(rfc,param_grid,cv=10)
GS.fit(data.data,data.target)
end = time.time()
print("循环运行时间:%.2f秒"%(end-start))
print(GS.best_params_)
print(GS.best_score_)

输出如下:

循环运行时间:3052.67秒
{'max_depth': 16, 'max_features': 0.1, 'min_samples_leaf': 1, 'min_samples_split': 3, 'n_estimators': 143}
0.9599332220367279

可以看到,精确度又上升了一点,此时,我们得到的新旧参数对比如下:

参数旧值新值n_estimators117143max_depth1616min_samples_leaf11min_samples_split23max_features0.10.1

对比一下新旧参数,可以看到参数变化还是比较大的,尤其是树的棵数这个参数。当然,这里主要原因是我们用来做示例的这个预置的数据集只有1797条数据,导致参数的随机性太大,在实际使用中数据集数量都是十万百万级的,不会出现我们手动调整的参数和小范围网格搜索参数差别这么大的情况。

最后需要说明的一点是:随机森林相对于决策树来说运行较慢,在调参时可以将参数搜索范围设置得小一些。

当然,这只是我个人的调参顺序,仅用来参考,没必要这么固化。实际调参时可以根据实际情况做一些调整。还是那句话:正是调参过程充满的各种不确定性,才是调参的真正魅力所在。

五、本系列相关文章

  • 机器学习超详细实践攻略(1):盘点scikit-learn里那些有趣又有用的彩蛋级入门数据集
  • 机器学习超详细实践攻略(8):使用scikit-learn构建模型的通用模板【万字长文】
  • ​机器学习超详细实践攻略(9):决策树算法详解及小白都能看懂的调参指南
  • 机器学习超详细实践攻略(21):三板斧干掉样本不均衡问题之1——过(欠)采样
  • 机器学习超详细实践攻略(22):三板斧干掉样本不均衡问题之2——对正负样本设置不同权重
  • 机器学习超详细实践攻略(23):三板斧干掉样本不均衡问题之3——通过集成学习方法解决样本不均衡

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/340798.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

http端口_PhpStorm 修改默认端口号63342

PhpStorm 修改默认端口号63342​blog.csdn.net关键词PhpStorm phpStorm phpstorm 修改默认端口号63342 8080 80步骤1.打开Settings2. Build, Execution, Deployment→Deployment3.点击添加,选择In place起一个名字(可以随便起)在Web server U…

rds mysql 磁盘空间,RDS MySQL 空间问题的原因和解决

other_size- 系统文件和临时文件使用空间data_size- 数据文件使用空间binlog_size- Binlog 文件占用空间注:获取实例诊断报告的步骤请参考如何访问RDS 实例诊断报告。2. 解决RDS 实例支持单独升级磁盘空间,升级磁盘空间是解决空间问题的有效方式之一。下…

微信小程序 全局变量异步函数_微信小程序【生命周期】

小程序分为应用、页面和组件三个部分,所以小程序的生命周期涉及以下应用的生命周期页面的生命周期组件的声明周期应用的生命周期对页面生命周期的影响应用的生命周期App() 函数用来注册一个小程序。接受一个 Object 参数,其指定小程序的生命周期回调等。…

Java / Spring:如何快速生成整个数据库CRUD REST API

随着时间的流逝,Spring框架已成为Java中使用最广泛的Web开发框架之一,这一点已变得显而易见。 在接下来的十年之际,Spring最受欢迎的模块Spring Boot刚刚进行了重大更新。 新的Spring Boot版本“ 2.2.0”和年份“ 2020”几乎完美匹配。 因此…

python界面长什么样图片_python界面是什么样的

安装完Python,在命令行输入“python”之后,如果成功,会得到类似于下面的窗口:可以看到,结尾有3个>符号(>>>)。>>>被叫做Python命令提示符(prompt)&…

python表格控件_python GUI库图形界面开发之PyQt5表格控件QTableView详细使用方法与实例...

PyQt5表格控件QTableView简介 在通常情况下,一个应用需要和一批数据进行交互,然后以表格的形式输出这些信息,这时就需要用到QTableView类了,在QTableView中可以使用自定义的数据模型来显示内容,通过setModel来绑定数据…

Linux文件系统为,浅析Linux文件系统

原标题:浅析Linux文件系统一、文件系统层次分析由上而下主要分为用户层、VFS层、文件系统层、缓存层、块设备层、磁盘驱动层、磁盘物理层用户层最上面用户层就是我们日常使用的各种程序,需要的接口主要是文件的创建、删除、打开、关闭、写、读等。VFS层我…

求解出n以内所有能被5整除的正整数的乘积_所有最常见最经典的算法题都在这里了...

1、一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到…

linux lvm 系统快照,系统运维|在 LVM中 录制逻辑卷快照并恢复(第三部分)

LVM快照是以空间换时间时间的方式制作的lvm卷副本。它只在lvm中工作,并只在源逻辑卷发生改变时占用快照卷的空间。如果源卷的变化达到1GB这么大,快照卷同样也会产生这样大的改变。因而,对于空间有效利用的最佳途径,就是总是进行小…

python语言变量随时声明_2. Go语言五种变量创建的方法

对于只有 Python 语言经验的朋友,也许会不太理解声明这个词,在 Python 中直接拿来就用,也不用声明类型啥的。 Go 语言是静态类型语言,由于编译时,编译器会检查变量的类型,所以要求所有的变量都要有明确的类…

会java需要多久能学会python_java好学吗?零基础学java要多久?

java好学吗?零基础学java要多久? 时间:2019-05-21 来源:华清远见 2019年3月,tiOBE 公布了编程语言排行榜,正如官方所说,本月的排名几乎没有任何有趣的变化,排名前十的依然是&…

jboss架构_检查Red Hat JBoss BRMS部署架构的规则和事件(第二部分)

jboss架构(文章来宾与北美红帽公司高级中间件顾问约翰赫洛克 ( John Hurlocker)合着) 在这周的技巧中,我们将放慢速度,并仔细研究可能的Red Hat JBoss BRMS部署体系结构。 在谈论部署体系结构时&#xff…

TestNG中的参数化– DataProvider和TestNG XML(带有示例)

测试自动化,或所谓的自动化测试,并不像听起来那样容易。 必须考虑所有可能的用户交互的所有排列和组合,并且在此基础上,您将必须创建测试脚本以通过多种浏览器和OS组合来验证Web应用程序。 这就是参数化在Selenium自动化测试中起关…

zbrush 添加纹理贴图_想学习3D游戏模型,3Dmax、MAYA和ZBrush都需要掌握吗?

想从事游戏行业的建模的话,模型和贴图的知识都得学,MAYA和3DMAX只能说是基本要学的,Zbrush能够提升个人价值,之后能给你建好的模型做出好看的贴图,才能算是一个游戏建模方面能干活的合格从业人员。新手入门的话&#x…

file.getpath_Java中File的getPath(),getCanonicalPath()和getAbsolutePath()之间的区别...

file.getpathFile API在Java中非常重要,因为它使文件系统可以访问Java程序。 尽管Java的文件API丰富,但是使用它们时仍需要了解很多细节。 关于文件路径的常见查询程序员之一是getPath() , getCanonicalPath()和getAbsolutePath()方法之间的区…

linux 在线帮助,linux获取在线帮助

Linux系统的帮助文档非常丰富。帮助手册提供命令的使用说明。比如你若是想了解ls命令的用法,只需运行:$ man ls帮助手册旨在提供基础知识和参考信息,有时会有一些实例和交叉索引,但是基本没有那种教程式的文档。帮助手册会按系统排…

linux中samba详解,详解linux系列之samba的安装及配置

上篇博文中我介绍了FTP,今天我们来介绍一下samba实现文件共享。这个比FTP更好点,因为对用户的权限可以通过samba权限和系统权限交叉使用,取最严格的。可以让windows更容易的从linux系统上存取文件,还有samba也可以让linux上面的打…

使用Apache Kafka,Kubernetes和Envoy,Istio,Linkerd的服务网格和云原生微服务

微服务架构不是免费的午餐 ! 微服务需要解耦,灵活,操作透明,数据感知和弹性。 过去几年的大多数材料仅讨论具有紧密耦合且不可扩展的技术(如REST / HTTP)的点对点体系结构。 这篇博客文章介绍了Apache Kafk…

单片机控制三相异步电动机正反转c语言程序,请用PLC控制一台普通三相异步电动机的正反转控制,设计其控制程序梯形图及主电路...

PLC的编程方法及步骤。总的步骤主要有三步:一、根据电路图选择电器元件及PLC的型号,其中包括确定PLC的输入输出点位、确定PLC的输出类型,也需考虑某些功能是否能扩展、价格等;二、设计好PLC控制的外围元器件的原理图。这里面包括有…

0x80070003系统找不到指定路径_Win7系统中gpedit.msc找不到应该如何解决?

Win7x系统gpedit.msc找不到怎么办?最近有用户反映,电脑当中的gpedit.msc找不到了,gpedit.msc就是我们的策略组,对于我们的电脑来说是非常重要的,那么gpedit.msc找不到应该如何解决呢?接下来就为大家分享win…