/// <summary> /// 调用BeginSampleEvent /// </summary> /// <param name="currentIteration"> /// 当前训练迭代 /// </param> /// <param name="currentSample"> /// 当前样品已成功训练 /// </param> protected virtual void OnEndSample(int currentIteration, TrainingSample currentSample) { if (EndSampleEvent != null) { EndSampleEvent(this, new TrainingSampleEventArgs(currentIteration, currentSample)); } }
/// <summary> /// 训练给定训练集的神经网络(批处理训练) /// </summary> /// <param name="trainingSet"> /// 使用的训练集 /// </param> /// <param name="trainingEpochs"> /// 训练时期数。 (所有样本在每个训练时期以一些随机顺序训练) /// </param> /// <exception cref="ArgumentNullException"> /// 如果<c> trainingSet </ c>是<c> null </ c> /// </exception> /// <exception cref="ArgumentException"> /// 如果<c> trainingEpochs </ c>为零或负值 /// </exception> public virtual void Learn(TrainingSet trainingSet, int trainingEpochs) { // 验证 Helper.ValidateNotNull(trainingSet, "trainingSet"); Helper.ValidatePositive(trainingEpochs, "trainingEpochs"); if ((trainingSet.InputVectorLength != inputLayer.NeuronCount) || (trainingMethod == TrainingMethod.Supervised && trainingSet.OutputVectorLength != outputLayer.NeuronCount) || (trainingMethod == TrainingMethod.Unsupervised && trainingSet.OutputVectorLength != 0)) { throw new ArgumentException("Invalid training set"); } // 重置isStopping isStopping = false; // 重新初始化网络 Initialize(); for (int currentIteration = 0; currentIteration < trainingEpochs; currentIteration++) { int[] randomOrder = Helper.GetRandomOrder(trainingSet.TrainingSampleCount); // 开始新的训练时期 OnBeginEpoch(currentIteration, trainingSet); // 检查抖动时期 if (jitterEpoch > 0 && currentIteration % jitterEpoch == 0) { for (int i = 0; i < connectors.Count; i++) { connectors[i].Jitter(jitterNoiseLimit); } } for (int index = 0; index < trainingSet.TrainingSampleCount; index++) { TrainingSample randomSample = trainingSet[randomOrder[index]]; // 学习随机训练样本 OnBeginSample(currentIteration, randomSample); LearnSample(trainingSet[randomOrder[index]], currentIteration, trainingEpochs); OnEndSample(currentIteration, randomSample); // 检查我们是否需要停止 if (isStopping) { isStopping = false; return; } } // 训练时期成功完成 OnEndEpoch(currentIteration, trainingSet); // 检查我们是否需要停止 if (isStopping) { isStopping = false; return; } } }
/// <summary> /// Trains the neural network for the given training set (Batch Training) /// </summary> /// <param name="trainingSet"> /// The training set to use /// </param> /// <param name="trainingEpochs"> /// Number of training epochs. (All samples are trained in some random order, in every /// training epoch) /// </param> /// <exception cref="ArgumentNullException"> /// if <c>trainingSet</c> is <c>null</c> /// </exception> /// <exception cref="ArgumentException"> /// if <c>trainingEpochs</c> is zero or negative /// </exception> public virtual void Learn(TrainingSet trainingSet, int trainingEpochs) { // Validate Helper.ValidateNotNull(trainingSet, "trainingSet"); Helper.ValidatePositive(trainingEpochs, "trainingEpochs"); if ((trainingSet.InputVectorLength != inputLayer.NeuronCount) || (trainingMethod == TrainingMethod.Supervised && trainingSet.OutputVectorLength != outputLayer.NeuronCount) || (trainingMethod == TrainingMethod.Unsupervised && trainingSet.OutputVectorLength != 0)) { throw new ArgumentException("Invalid training set"); } // Reset isStopping isStopping = false; // Re-Initialize the network Initialize(); for (int currentIteration = 0; currentIteration < trainingEpochs; currentIteration++) { int[] randomOrder = Helper.GetRandomOrder(trainingSet.TrainingSampleCount); // Beginning a new training epoch OnBeginEpoch(currentIteration, trainingSet); // Check for Jitter Epoch if (jitterEpoch > 0 && currentIteration % jitterEpoch == 0) { for (int i = 0; i < connectors.Count; i++) { connectors[i].Jitter(jitterNoiseLimit); } } for (int index = 0; index < trainingSet.TrainingSampleCount; index++) { TrainingSample randomSample = trainingSet[randomOrder[index]]; // Learn a random training sample OnBeginSample(currentIteration, randomSample); LearnSample(trainingSet[randomOrder[index]], currentIteration, trainingEpochs); OnEndSample(currentIteration, randomSample); // Check if we need to stop if (isStopping) { isStopping = false; return; } } // Training Epoch successfully complete OnEndEpoch(currentIteration, trainingSet); // Check if we need to stop if (isStopping) { isStopping = false; return; } } }
/// <summary> /// 训练给定训练样本的网络(在线训练模式)。 注意这个方法仅训练样本一次,而不管当前的时期是什么。 参数只是用来找出训练进度,并根据它调整参数。 /// </summary> /// <param name="trainingSample"> /// 培训样品使用 /// </param> /// <param name="currentIteration"> /// 当前训练迭代 /// </param> /// <param name="trainingEpochs"> /// 训练时期数 /// </param> /// <exception cref="ArgumentNullException"> /// 如果<c> trainingSample </ c>为<c> null </ c> /// </exception> /// <exception cref="ArgumentException"> /// 如果<c> trainingEpochs </ c>不为正 /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// 如果<c> currentIteration </ c>为负,或者如果它不小于<c> trainingEpochs </ c> /// </exception> public virtual void Learn(TrainingSample trainingSample, int currentIteration, int trainingEpochs) { Helper.ValidateNotNull(trainingSample, "trainingSample"); Helper.ValidatePositive(trainingEpochs, "trainingEpochs"); Helper.ValidateWithinRange(currentIteration, 0, trainingEpochs - 1, "currentIteration"); OnBeginSample(currentIteration, trainingSample); LearnSample(trainingSample, currentIteration, trainingEpochs); OnEndSample(currentIteration, trainingSample); }
/// <summary> /// 向训练集添加新的监督训练样本。 如果已经存在,它将被替换。 /// </summary> /// <param name="sample"> /// 要添加的示例 /// </param> /// <exception cref="ArgumentNullException"> /// 如果<c> sample </ c>为<c> null </ c> /// </exception> /// <exception cref="ArgumentException"> /// 如果输入向量或输出向量的大小与其预期大小不同 /// </exception> public void Add(TrainingSample sample) { // 验证 Helper.ValidateNotNull(sample, "sample"); if (sample.InputVector.Length != inputVectorLength) { throw new ArgumentException ("Input vector must be of size " + inputVectorLength, "sample"); } if (sample.OutputVector.Length != outputVectorLength) { throw new ArgumentException ("Output vector must be of size " + outputVectorLength, "sample"); } // 请注意,正在添加引用。 (样本是不可变的) trainingSamples.Add(sample); }
/// <summary> /// Adds a new supervised training sample to the training set. If already exists, it will /// be replaced. /// </summary> /// <param name="sample"> /// The sample to add /// </param> /// <exception cref="ArgumentNullException"> /// If <c>sample</c> is <c>null</c> /// </exception> /// <exception cref="ArgumentException"> /// If sizes of input vector or output vector are different from their expected sizes /// </exception> public void Add(TrainingSample sample) { // Validation Helper.ValidateNotNull(sample, "sample"); if (sample.InputVector.Length != inputVectorLength) { throw new ArgumentException ("Input vector must be of size " + inputVectorLength, "sample"); } if (sample.OutputVector.Length != outputVectorLength) { throw new ArgumentException ("Output vector must be of size " + outputVectorLength, "sample"); } // Note that the reference is being added. (Sample is immutable) trainingSamples.Add(sample); }
/// <summary> /// Determine whether the given object is equal to this instance /// </summary> /// <param name="obj"> /// The object to compare with this instance /// </param> /// <returns> /// <c>true</c> if the given object is equal to this instance, <c>false</c> otherwise /// </returns> public override bool Equals(object obj) { if (obj is TrainingSample) { TrainingSample sample = (TrainingSample)obj; int size; if ((size = sample.inputVector.Length) == inputVector.Length) { for (int i = 0; i < size; i++) { if (inputVector[i] != sample.inputVector[i]) { return(false); } } return(true); } } return(false); }
/// <summary> /// A protected helper function used to train single learning sample /// </summary> /// <param name="trainingSample"> /// Training sample to use /// </param> /// <param name="currentIteration"> /// Current training epoch (Assumed to be positive and less than <c>trainingEpochs</c>) /// </param> /// <param name="trainingEpochs"> /// Number of training epochs (Assumed to be positive) /// </param> protected abstract void LearnSample(TrainingSample trainingSample, int currentIteration, int trainingEpochs);
/// <summary> /// Determines whether the training sample is present in the set /// </summary> /// <param name="sample"> /// The sample to locate /// </param> /// <returns> /// <c>true</c> if present, <c>false</c> otherwise /// </returns> public bool Contains(TrainingSample sample) { return trainingSamples.Contains(sample); }
/// <summary> /// Creates a new instance of this class /// </summary> /// <param name="trainingIteration"> /// Current training iteration /// </param> /// <param name="trainingSample"> /// The training sample associated with the event /// </param> public TrainingSampleEventArgs(int trainingIteration, TrainingSample trainingSample) { this.trainingIteration = trainingIteration; this.trainingSample = trainingSample; }
/// <summary> /// 确定训练样本是否存在于集合中 /// </summary> /// <param name="sample"> /// 要定位的示例 /// </param> /// <returns> /// <c> true </ c>如果存在,<c> false </ c> /// </returns> public bool Contains(TrainingSample sample) { return(trainingSamples.Contains(sample)); }
/// <summary> /// 删除给定的训练样本 /// </summary> /// <param name="sample"> /// 要除去的样品 /// </param> /// <returns> /// <c> true </ c>如果成功,<c> false </ c> /// </returns> public bool Remove(TrainingSample sample) { return(trainingSamples.Remove(sample)); }
/// <summary> /// Roda as redes para cada um dos treinamentos, separando os treinamentos por dia /// Calcula também a taxa média de acerto de cada rede neural por dia /// </summary> /// <param name="dadosTreinamento"></param> /// <param name="redesPrevisaoFinanceira"></param> /// <returns></returns> private static Dictionary<int, TrainingSet> SelecionarTreinamentosPorDia(ConfiguracaoCaptacaoRedes configuracaoCaptacao) { int tamanhoEntrada = configuracaoCaptacao.RedesPrevisao.Max(rp => rp.JanelaEntrada); List<Treinamento> treinamentos = DataBaseUtils.DataBaseUtils.SelecionarTreinamentos(configuracaoCaptacao.Dados, tamanhoEntrada, totalDiasPrevisao, 2); //Dictionary<int, Dictionary<List<double>, List<double>>> dadosTreinamentoPorShift = new Dictionary<int, Dictionary<List<double>, List<double>>>(); ////Resgata o maior tamanho das entradas das redes neurais ////Cria o dicionario de input output por shift //for (int numShift = 0; numShift < quantidadeShifts; numShift++) //{ // //Seleciona oa dados antes do shift // dadosTreinamentoPorShift.Add(numShift, SelecionarInput_Output(configuracaoCaptacao.Dados.Take((configuracaoCaptacao.Dados.Count / (quantidadeShifts - 1)) * numShift).ToList(), tamanhoEntrada)); // //Seleciona os dados depois do shift // dadosTreinamentoPorShift[numShift].ToList().AddRange(SelecionarInput_Output(configuracaoCaptacao.Dados.Skip((configuracaoCaptacao.Dados.Count / (quantidadeShifts - 1)) * (numShift + 1)).ToList(), tamanhoEntrada)); //} //Inicializa todos os dias da previsao for (int diaTreinamento = 0; diaTreinamento < totalDiasPrevisao; diaTreinamento++) { foreach (RedePrevisaoFinanceira redePrevisao in configuracaoCaptacao.RedesPrevisao) { redePrevisao.TaxaMediaAcertoPorDia.Add(diaTreinamento, 0); } } Dictionary<int, TrainingSet> treinamentosPorDia = new Dictionary<int, TrainingSet>(); for (int dia = 0; dia < totalDiasPrevisao; dia++) { treinamentosPorDia.Add(dia, new TrainingSet(tamanhoEntrada, configuracaoCaptacao.RedesPrevisao.Count)); } //Roda as redes para cada um dos dados de treinamento selecionados foreach (Treinamento treinamento in treinamentos) { //Guarda um historico dos outputs das redes para tratar as redes que tem output menor do que o tamanho da previsao List<List<double>> outputsRedes = new List<List<double>>(); List<double[]> taxasAcertoRedes = new List<double[]>(); foreach (RedePrevisaoFinanceira redePrevisao in configuracaoCaptacao.RedesPrevisao) { Network redeNeural = redePrevisao.RedeNeuralPrevisaoFinanceiraPorDivisaoCrossValidation[treinamento.DivisaoCrossValidation]; //Roda a rede neural, gerando a previsao \/ como a rede pode receber um input menor do que os treinamentos, pegamos apenas os ultimos registros do mesmo double[] outputPrevisao = redeNeural.Run(treinamento.Input.Skip(treinamento.Input.Count - redePrevisao.JanelaEntrada).Take(redePrevisao.JanelaEntrada).ToArray()); //Alimenta o historico de previsoes de cada rede outputsRedes.Add(outputPrevisao.ToList()); double[] taxaAcertoPorDia = new double[totalDiasPrevisao]; for (int diasPrevistosRN = 0; diasPrevistosRN < outputPrevisao.Length; diasPrevistosRN++) { //Calcula a taxa de acerto da previsao double ta = Math.Min(outputPrevisao[diasPrevistosRN], treinamento.Output[diasPrevistosRN]) / Math.Max(outputPrevisao[diasPrevistosRN], treinamento.Output[diasPrevistosRN]); taxaAcertoPorDia[diasPrevistosRN] = ta; redePrevisao.TaxaMediaAcertoPorDia[diasPrevistosRN] += ta; } taxasAcertoRedes.Add(taxaAcertoPorDia); } //Lista com o melhor desultado de cada dia (cada item da lista corresponde a um dia..) List<double> melhoresResultadosDia = new List<double>(treinamento.Input); //Trata as taxas de acerto que não foram calculadas pois a rede tem output menor do que a quantidade de dias da previsao for (int dia = 1; dia < totalDiasPrevisao; dia++) { //Recupera o indice da rede que tem a melhor taxa de acerto para o dia anterior int indMelhorRedeParaODiaAnterior = taxasAcertoRedes.IndexOf(taxasAcertoRedes.OrderByDescending(taxasAcertoRede => taxasAcertoRede[dia - 1]).First()); //Adiciona o melhor resultado a lista de melhores resultados melhoresResultadosDia.Add(outputsRedes[indMelhorRedeParaODiaAnterior][dia - 1]); for (int indRede = 0; indRede < configuracaoCaptacao.RedesPrevisao.Count; indRede++) { //Verifica se a taxa de acerto do dia para a rede ja foi calculada if (taxasAcertoRedes[indRede][dia] == 0) { //Ultiliza os ultimos melhores dados para fazer uma nova previsao double[] inputRede = melhoresResultadosDia.Skip(melhoresResultadosDia.Count - configuracaoCaptacao.RedesPrevisao[indRede].JanelaEntrada).Take(configuracaoCaptacao.RedesPrevisao[indRede].JanelaEntrada).ToArray(); double[] outputRede = configuracaoCaptacao.RedesPrevisao[indRede].RedeNeuralPrevisaoFinanceiraPorDivisaoCrossValidation[treinamento.DivisaoCrossValidation].Run(inputRede); //Adiciona o dia previsto na lista de outputs outputsRedes[indRede].Add(outputRede.Last()); //Calcula a taxa de acerto da previsao double ta = Math.Min(outputRede.Last(), treinamento.Output[dia]) / Math.Max(outputRede.Last(), treinamento.Output[dia]); //Adiciona a taxa de acerto da rede para o dia taxasAcertoRedes[indRede][dia] = ta; //Atualiza a taxa de acerto da rede configuracaoCaptacao.RedesPrevisao[indRede].TaxaMediaAcertoPorDia[dia] += ta; } } } for (int dia = 0; dia < totalDiasPrevisao; dia++) { double[] outputCaptacao = new double[configuracaoCaptacao.RedesPrevisao.Count]; for (int indRede = 0; indRede < configuracaoCaptacao.RedesPrevisao.Count; indRede++) { outputCaptacao[indRede] = taxasAcertoRedes[indRede][dia]; } TrainingSample ts = new TrainingSample(treinamento.Input.ToArray(), outputCaptacao); treinamentosPorDia[dia].Add(ts); } } //Divide a taxa de acerto pela quantidade de treinamentos para saber a taxa média foreach (RedePrevisaoFinanceira redePrevisao in configuracaoCaptacao.RedesPrevisao) { for (int i = 0; i < totalDiasPrevisao; i++) { redePrevisao.TaxaMediaAcertoPorDia[i] /= treinamentos.Count; } } return treinamentosPorDia; }
/// <summary> /// 一个受保护的帮助函数,用于训练单个学习样本 /// </summary> /// <param name="trainingSample"> /// 培训样品使用 /// </param> /// <param name="currentIteration"> /// 当前训练时期(假设为正且小于<c> trainingEpochs </ c>) /// </param> /// <param name="trainingEpochs"> /// 训练时期数(假定为正) /// </param> protected abstract void LearnSample(TrainingSample trainingSample, int currentIteration, int trainingEpochs);
/// <summary> /// Removes the given training sample /// </summary> /// <param name="sample"> /// The sample to remove /// </param> /// <returns> /// <c>true</c> if successful, <c>false</c> otherwise /// </returns> public bool Remove(TrainingSample sample) { return trainingSamples.Remove(sample); }
/// <summary> /// Trains the network for the given training sample (Online training mode). Note that this /// method trains the sample only once, irrespective of what current epoch is. The arguments /// are just used to find out training progress and adjust parameters depending on it. /// </summary> /// <param name="trainingSample"> /// Training sample to use /// </param> /// <param name="currentIteration"> /// Current training iteration /// </param> /// <param name="trainingEpochs"> /// Number of training epochs /// </param> /// <exception cref="ArgumentNullException"> /// If <c>trainingSample</c> is <c>null</c> /// </exception> /// <exception cref="ArgumentException"> /// If <c>trainingEpochs</c> is not positive /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// If <c>currentIteration</c> is negative or, if it is not less than <c>trainingEpochs</c> /// </exception> public virtual void Learn(TrainingSample trainingSample, int currentIteration, int trainingEpochs) { Helper.ValidateNotNull(trainingSample, "trainingSample"); Helper.ValidatePositive(trainingEpochs, "trainingEpochs"); Helper.ValidateWithinRange(currentIteration, 0, trainingEpochs - 1, "currentIteration"); OnBeginSample(currentIteration, trainingSample); LearnSample(trainingSample, currentIteration, trainingEpochs); OnEndSample(currentIteration, trainingSample); }
/// <summary> /// 创建此类的新实例 /// </summary> /// <param name="trainingIteration"> /// 当前训练迭代 /// </param> /// <param name="trainingSample"> /// 与事件相关联的训练样本 /// </param> public TrainingSampleEventArgs(int trainingIteration, TrainingSample trainingSample) { this.trainingIteration = trainingIteration; this.trainingSample = trainingSample; }
/// <summary> /// Invokes BeginSampleEvent /// </summary> /// <param name="currentIteration"> /// Current training iteration /// </param> /// <param name="currentSample"> /// Current sample which got trained successfully /// </param> protected virtual void OnEndSample(int currentIteration, TrainingSample currentSample) { if (EndSampleEvent != null) { EndSampleEvent(this, new TrainingSampleEventArgs(currentIteration, currentSample)); } }
//Train agent's neural network for specific input and desired output private void trainNeural(double[] input, double output) { double[] tmp = { output }; //Create the training sample for the neural network TrainingSample sample = new TrainingSample(input, tmp); //Train nn network.Learn(sample, 0, currentEpoch); }