def cost_overall(self, data): """ Costo promedio total de la red neuronal para un batch de M entradas {*features*, *label*}, dado por: :math:`C(W, b; x, y) = \\dfrac{1}{M} \displaystyle\sum\limits_{i}^M C_{FP}(W, b; x^{(i)}, y^{(i)}) + L1 + L2` donde :math:`C_{FP}` es el costo obtenido al final del Forward Pass durante el algoritmo de Backpropagation, y los términos *L1* y *L2* corresponden a las normas de regularización calculadas con las funciones :func:`~learninspy.core.model.NeuralNetwork.l1` y :func:`~learninspy.core.model.NeuralNetwork.l2` respectivamente. :param data: list de *pyspark.mllib.regression.LabeledPoint* :return: float (costo), tuple de :class:`~learninspy.core.neurons.LocalNeurons` (gradientes de W y b) .. note:: Para problemas de clasificación, el float *label* se convierte a un vector binario de dimensión K (dado por la cantidad de clases a predecir) mediante :func:`~learninspy.utils.data.label_to_vector` para así poder aplicar una función de costo en forma directa contra la predicción realizada por la softmax (que es un vector). """ # TODO: ver http://stats.stackexchange.com/questions/108381/how-to-avoid-nan-in-using-relu-cross-entropy features = map(lambda lp: lp.features, data) if self.params.classification is True: labels = map(lambda lp: label_to_vector(lp.label, self.params.units_layers[-1]), data) else: labels = map(lambda lp: [lp.label], data) # Loss avg overall cost, (nabla_w, nabla_b) = self._backprop(features[0], labels[0]) n = len(data) for f, l in zip(features, labels)[1:]: c, (n_w, n_b) = self._backprop(f, l) cost += c nabla_w = map(lambda (n1, n2): n1 + n2, zip(nabla_w, n_w)) nabla_b = map(lambda (n1, n2): n1 + n2, zip(nabla_b, n_b)) cost /= float(n) nabla_w = map(lambda n_l: n_l / float(n), nabla_w) nabla_b = map(lambda n_l: n_l / float(n), nabla_b) # Regularization if self.params.strength_l1 > 0.0: c, n_w = self.l1() cost += c nabla_w = map(lambda (n1, n2): n1 + n2, zip(nabla_w, n_w)) if self.params.strength_l2 > 0.0: c, n_w = self.l2() cost += c nabla_w = map(lambda (n1, n2): n1 + n2, zip(nabla_w, n_w)) return cost, (nabla_w, nabla_b)
def cost_single(self, features, label): """ Costo total de la red neuronal para una entrada singular {*features*, *label*}, dado por: :math:`C(W, b; x, y) = C_{FP}(W, b; x, y) + L1 + L2` donde :math:`C_{FP}` es el costo obtenido al final del Forward Pass durante el algoritmo de Backpropagation, y los términos *L1* y *L2* corresponden a las normas de regularización calculadas con las funciones :func:`~learninspy.core.model.NeuralNetwork.l1` y :func:`~learninspy.core.model.NeuralNetwork.l2` respectivamente. :param features: *numpy.ndarray* :param label: float o *numpy.ndarray* :return: float (costo), tuple de :class:`~learninspy.core.neurons.LocalNeurons` (gradientes de W y b) .. note:: Para problemas de clasificación, el float *label* se convierte a un vector binario de dimensión K (dado por la cantidad de clases a predecir) mediante :func:`~learninspy.utils.data.label_to_vector` para así poder aplicar una función de costo en forma directa contra la predicción realizada por la softmax (que es un vector). """ # 'label' se debe vectorizar para que se pueda utilizar en una fun_loss sobre un Neurons (arreglo) # - Si la tarea de la red es de clasificación, entonces 'label' se debe convertir a vector binario. # Así, se puede aplicar directamente a una función de costo contra la salida del softmax (vector). # - Si la tarea de la red es de regresión, entonces 'label' pasa a ser un list(label) if self.params.classification is True: label = label_to_vector(label, self.params.units_layers[-1]) # n_classes dado por la dim de la últ capa else: label = [label] # Conversion a list necesaria para loss que opera con arreglos cost, (nabla_w, nabla_b) = self._backprop(features, label) if self.params.strength_l1 > 0.0: c, n_w = self.l1() cost += c nabla_w = map(lambda (n1, n2): n1 + n2, zip(nabla_w, n_w)) if self.params.strength_l2 > 0.0: c, n_w = self.l2() cost += c nabla_w = map(lambda (n1, n2): n1 + n2, zip(nabla_w, n_w)) return cost, (nabla_w, nabla_b)