Algoritmo de aprendizado de máquina 丨 teste de comparação de desempenho implementado por algoritmo de floresta aleatório

 

Teste de comparação de desempenho implementado por algoritmo de floresta aleatório

A floresta aleatória é um algoritmo de aprendizado de máquina comumente usado, que pode ser usado tanto para problemas de classificação quanto para problemas de regressão. Este artigo compara e testa a implementação de algoritmos de floresta aleatórios em quatro plataformas: scikit-learn, Spark MLlib, DolphinDB e xgboost. Os indicadores de avaliação incluem uso de memória, velocidade de execução e precisão de classificação. Este teste usa dados simulados como entrada para treinamento de classificação binária e usa o modelo gerado para prever os dados simulados.

1. Software de teste

As versões da plataforma usadas neste teste são as seguintes:

scikit-learn : Python 3.7.1 , scikit-learn 0.20.2

Spark MLlib : Spark 2.0.2 , Hadoop 2.7.2

DolphinDB : 0,82

xgboost : Pacote Python , 0,81

2. Configuração do ambiente

CPU: Intel (R) Xeon (R) CPU E5-2650 v4 2,20 GHz (24 núcleos e 48 threads no total)

RAM : 512 GB

Sistema operacional: CentOS Linux versão 7.5.1804

Ao testar em cada plataforma, os dados serão carregados na memória e então calculados, de forma que o desempenho do algoritmo de floresta aleatória não tem nada a ver com o disco.

3. Geração de dados

Este teste usa o script DolphinDB para gerar dados de simulação e exportá-los como um arquivo CSV. O conjunto de treinamento é dividido igualmente em duas categorias. As colunas de recursos de cada categoria estão sujeitas a dois centros diferentes, o mesmo desvio padrão e distribuições normais multivariadas independentes de pares N (0, 1) e N (2 / sqrt (20), 1 ) Não há valores nulos no conjunto de treinamento.

Suponha que o tamanho do conjunto de treinamento seja de n linhas e p colunas. Neste teste, o valor de n é 10.000, 100.000, 1.000.000 e o valor de p é 50.

Como o conjunto de teste e o conjunto de treinamento são independentes e distribuídos de forma idêntica, o tamanho do conjunto de teste não tem efeito significativo na avaliação da precisão do modelo. Este teste usa 1000 linhas de dados simulados como o conjunto de teste para todos os conjuntos de treinamento de tamanhos diferentes.

Consulte o Apêndice 1 para o script DolphinDB que gera dados de simulação.

4. Parâmetros do modelo

Os seguintes parâmetros são usados ​​para treinamento de modelo de floresta aleatório em cada plataforma:

  • Número de árvores: 500
  • Profundidade máxima: A profundidade máxima de 10 e 30 foram testadas em 4 plataformas.
  • O número de recursos selecionados ao dividir os nós: a raiz quadrada do número total de recursos, que é inteiro (sqrt (50)) = 7
  • Índice de impureza ao dividir nós: índice de Gini, este parâmetro é válido apenas para Python scikit-learn, Spark MLlib e DolphinDB
  • Número de intervalos de amostra: 32, este parâmetro é válido apenas para Spark MLlib e DolphinDB
  • Número de tarefas simultâneas: número de threads de CPU, 48 para Python scikit-learn, Spark MLlib e DolphinDB e 24 para xgboost.

Ao testar o xgboost, tentei diferentes valores do parâmetro nthread (representando o número de threads simultâneos em tempo de execução). Porém, quando o valor do parâmetro é o número de threads neste ambiente de teste (48), o desempenho não é ideal. Observa-se ainda que quando o número de encadeamentos é inferior a 10, o desempenho está positivamente correlacionado com o valor. Quando o número de threads é maior que 10 e menor que 24, a diferença de desempenho de diferentes valores não é óbvia.Após isso, o desempenho diminui quando o número de threads aumenta. Este fenômeno também foi discutido na comunidade xgboost . Portanto, o número final de encadeamentos usados ​​no xgboost neste teste é 24.

5. Resultados do teste

Veja o apêndice 2 ~ 5 para o script de teste.

Quando o número de árvores é 500 e a profundidade máxima é 10, os resultados do teste são mostrados na seguinte tabela:

ae1efdeaf1ae22496cb90824a188bc47.png

Quando o número de árvores é 500 e a profundidade máxima é 30, os resultados do teste são mostrados na seguinte tabela:

316d688e45847c1bbcc897ab743af876.png

Em termos de precisão, a precisão de Python scikit-learn, Spark MLlib e DolphinDB são semelhantes, ligeiramente superiores à implementação de xgboost; em termos de desempenho, de alto a baixo, eles são DolphinDB, Python scikit-learn, xgboost, Spark MLlib .

Neste teste, a implementação do Python scikit-learn usa todos os núcleos da CPU.

A implementação do Spark MLlib não faz uso completo de todos os núcleos da CPU e tem o maior uso de memória. Quando o volume de dados é 10.000, a taxa de ocupação máxima da CPU é de cerca de 8%. Quando o volume de dados é 100.000, a taxa de ocupação máxima da CPU é de cerca de 25%. Em 1.000.000, ele interromperá a execução devido à memória insuficiente.

A implementação do banco de dados DolphinDB usa todos os núcleos de CPU, e é a mais rápida de todas as implementações, mas sua pegada de memória é de 2 a 7 vezes maior do que scikit-learn e de 3 a 9 vezes maior do que xgboost. A implementação do algoritmo de floresta aleatória do DolphinDB fornece o parâmetro numJobs, que pode ser ajustado para reduzir o grau de paralelismo, reduzindo assim o uso de memória. Para obter detalhes, consulte o manual do usuário DolphinDB .

xgboost é frequentemente usado no treinamento de árvores impulsionadas e também pode executar algoritmos de floresta aleatórios. É um caso especial quando o número de iterações do algoritmo é 1. Na verdade, o Xgboost tem o desempenho mais alto com cerca de 24 threads, e sua utilização de threads de CPU não é tão boa quanto Python e DolphinDB, e a velocidade não é tão boa quanto ambos. Sua vantagem reside no menor uso de memória. Além disso, a implementação específica do xgboost também é diferente daquela de outras plataformas. Por exemplo, não há processo de bootstrap, usando amostragem sem substituição em vez de amostragem com substituição. Isso pode explicar porque sua precisão é um pouco menor do que outras plataformas.

6. Resumo

O algoritmo de floresta aleatória do Python scikit-learn atinge um desempenho equilibrado, sobrecarga de memória e precisão. O desempenho da implementação do Spark MLlib é muito inferior a outras plataformas em termos de desempenho e sobrecarga de memória. O algoritmo de floresta aleatória do DolphinDB atinge o melhor desempenho, e o algoritmo de floresta aleatória do DolphinDB e o banco de dados são perfeitamente integrados.Os usuários podem treinar e prever diretamente os dados no banco de dados e fornecer o parâmetro numJobs para obter a diferença entre memória e velocidade. Saldo. A floresta aleatória de xgboost é apenas um caso especial quando o número de iterações é 1 e a implementação específica é bastante diferente de outras plataformas.O melhor cenário de aplicação é a árvore impulsionada.

apêndice

1. Script DolphinDB que simula geração de dados

def genNormVec (cls, a, stdev, n) { 
	return norm (cls * a, stdev, n)} def genNormData (dataSize, colSize, clsNum, scale, stdev) { 
	t = table (dataSize: 0, `cls join ( "col" + string (0 .. (colSize-1))), INT join take (DOUBLE, colSize)) 
	classStat = groupby (count, 1..dataSize, rand (clsNum, dataSize)) 
	for (linha em classStat) { 
		cls = row.groupingKey 
		classSize = row.count 
		cols = [take (cls, classSize)] 
		para (i em 0: colSize) 
			cols.append! (genNormVec (cls, scale, stdev, classSize)) 
		tmp = table (dataSize) : 0, `cls join (" col "+ string (0 .. (colSize-1))), INT join take (DOUBLE, colSize)) 
		inserir em valores t (cols) 
		cols = NULL 
		tmp = NULL 
	}
	return t} colSize = 50clsNum = 2t1m = genNormData (10000, colSize, clsNum, 2 / sqrt (20), 1.0) saveText (t1m, "t10k.csv") t10m = genNormData (100000, colSize, clsNum, 2 / sqrt ( 20), 1.0) saveText (t10m, "t100k.csv") t100m = genNormData (1000000, colSize, clsNum, 2 / sqrt (20), 1.0) saveText (t100m, "t1m.csv") t1000 = genNormData (1000, colSize, clsNum, 2 / sqrt (20), 1.0) saveText (t1000, "t1000.csv")

 

2. Script de predição e treinamento Python scikit-learn

import pandas as pdimport numpy as npfrom sklearn.ensemble import RandomForestClassifier, RandomForestRegressorfrom time import *

test_df = pd.read_csv("t1000.csv")def evaluate(path, model_name, num_trees=500, depth=30, num_jobs=1):
    df = pd.read_csv(path)
    y = df.values[:,0]
    x = df.values[:,1:]

    test_y = test_df.values[:,0]
    test_x = test_df.values[:,1:]

    rf = RandomForestClassifier(n_estimators=num_trees, max_depth=depth, n_jobs=num_jobs)
    start = time()
    rf.fit(x, y)
    end = time()
    elapsed = end - start
    print("Time to train model %s: %.9f seconds" % (model_name, elapsed))

    acc = np.mean(test_y == rf.predict(test_x))
    print("Model %s accuracy: %.3f" % (model_name, acc))

evaluate("t10k.csv", "10k", 500, 10, 48)    # choose your own parameter

 

3. Spark MLlib的训练和预测代码(Scala实现)

import org.apache.spark.mllib.tree.configuration.FeatureType.Continuousimport org.apache.spark.mllib.tree.model.{DecisionTreeModel, Node}object Rf {
  def main(args: Array[String]) = {
    evaluate("/t100k.csv", 500, 10)    // choose your own parameter 
  }

  def processCsv(row: Row) = {    val label = row.getString(0).toDouble    val featureArray = (for (i <- 1 to (row.size-1)) yield row.getString(i).toDouble).toArray    val features = Vectors.dense(featureArray)
    LabeledPoint(label, features)
  }

  def evaluate(path: String, numTrees: Int, maxDepth: Int) = {    val spark = SparkSession.builder.appName("Rf").getOrCreate()    import spark.implicits._    val numClasses = 2
    val categoricalFeaturesInfo = Map[Int, Int]()    val featureSubsetStrategy = "sqrt" 
    val impurity = "gini"
    val maxBins = 32

    val d_test = spark.read.format("CSV").option("header","true").load("/t1000.csv").map(processCsv).rdd
    d_test.cache()

    println("Loading table (1M * 50)")    val d_train = spark.read.format("CSV").option("header","true").load(path).map(processCsv).rdd
    d_train.cache()
    println("Training table (1M * 50)")    val now = System.nanoTime    val model = RandomForest.trainClassifier(d_train, numClasses, categoricalFeaturesInfo,
      numTrees, featureSubsetStrategy, impurity, maxDepth, maxBins)
    println(( System.nanoTime - now )/1e9)    val scoreAndLabels = d_test.map { point =>      val score = model.trees.map(tree => softPredict2(tree, point.features)).sum      if (score * 2 > model.numTrees)
        (1.0, point.label)      else
        (0.0, point.label)
    }    val metrics = new MulticlassMetrics(scoreAndLabels)
    println(metrics.accuracy)
  }

  def softPredict(node: Node, features: Vector): Double = {    if (node.isLeaf) {      //if (node.predict.predict == 1.0) node.predict.prob else 1.0 - node.predict.prob
      node.predict.predict
    } else {      if (node.split.get.featureType == Continuous) {        if (features(node.split.get.feature) <= node.split.get.threshold) {
          softPredict(node.leftNode.get, features)
        } else {
          softPredict(node.rightNode.get, features)
        }
      } else {        if (node.split.get.categories.contains(features(node.split.get.feature))) {
          softPredict(node.leftNode.get, features)
        } else {
          softPredict(node.rightNode.get, features)
        }
      }
    }
  }
  def softPredict2(dt: DecisionTreeModel, features: Vector): Double = {
    softPredict(dt.topNode, features)
  }
}

 

4. DolphinDB的训练和预测脚本

def createInMemorySEQTable(t, seqSize) {
	db = database("", SEQ, seqSize)
	dataSize = t.size()
	ts = ()	for (i in 0:seqSize) {
		ts.append!(t[(i * (dataSize/seqSize)):((i+1)*(dataSize/seqSize))])
	}	return db.createPartitionedTable(ts, `tb)
}def accuracy(v1, v2) {	return (v1 == v2).sum() \ v2.size()
}def evaluateUnparitioned(filePath, numTrees, maxDepth, numJobs) {
	test = loadText("t1000.csv")
	t = loadText(filePath); clsNum = 2; colSize = 50
	timer res = randomForestClassifier(sqlDS(<select * from t>), `cls, `col + string(0..(colSize-1)), clsNum, sqrt(colSize).int(), numTrees, 32, maxDepth, 0.0, numJobs)
	print("Unpartitioned table accuracy = " + accuracy(res.predict(test), test.cls).string())
}

evaluateUnpartitioned("t10k.csv", 500, 10, 48)    // choose your own parameter

 

5. xgboost的训练和预测脚本

import pandas as pdimport numpy as npimport xgboost as xgbfrom time import *def load_csv(path):
    df = pd.read_csv(path)
    target = df['cls']
    df = df.drop(['cls'], axis=1)    return xgb.DMatrix(df.values, label=target.values)

dtest = load_csv('/hdd/hdd1/twonormData/t1000.csv')def evaluate(path, num_trees, max_depth, num_jobs):
    dtrain = load_csv(path)
    param = {'num_parallel_tree':num_trees, 'max_depth':max_depth, 'objective':'binary:logistic',        'nthread':num_jobs, 'colsample_bylevel':1/np.sqrt(50)}
    start = time()
    model = xgb.train(param, dtrain, 1)
    end = time()
    elapsed = end - start
    print("Time to train model: %.9f seconds" % elapsed)
    prediction = model.predict (dtest)> 0.5 
    print ("Accuracy =% .3f"% np.mean (prediction == dtest.get_label ())) 

avaliar ('t10k.csv', 500, 10, 24) // escolha seu próprio parâmetro


Acho que você gosta

Origin blog.51cto.com/15022783/2572898
Recomendado
Clasificación