python - scipy.optimize.minimize 在神经网络中的使用

标签 python machine-learning scipy neural-network

尝试使用反向传播神经网络进行多类分类。我找到了this code并尝试去适应它。它基于 Machine Learning in Coursera from Andrew Ng 的选集。

我不太清楚这里scipy.optimize.minimize函数的实现。它在代码中仅使用一次。是否迭代更新网络的权重?我如何可视化(绘制)它的性能以查看它何时收敛?

使用此功能我可以调整哪些参数以获得更好的性能?我发现here常用参数列表:

  • 隐藏层中的神经元数量:这是我代码中的 hidden_​​layer_size=25
  • 学习率:我仍然可以使用内置最小化功能来调整学习率吗?
  • 动量:在我的例子中是reg_lambda=0吗?正则化参数以避免过度拟合,对吗?
  • 纪元:maxiter=500

这是我的训练数据(目标类别在最后一列):


65535, 3670, 65535, 3885, -0.73, 1
65535, 3962, 65535, 3556, -0.72, 1
65535, 3573, 65535, 3529, -0.61, 1
3758, 3123, 4117, 3173, -0.21, 0
3906, 3119, 4288, 3135, -0.28, 0
3750, 3073, 4080, 3212, -0.26, 0
65535, 3458, 65535, 3330, -0.85, 2
65535, 3315, 65535, 3306, -0.87, 2
65535, 3950, 65535, 3613, -0.84, 2
65535, 32576, 65535, 19613, -0.35, 3
65535, 16657, 65535, 16618, -0.37, 3
65535, 16657, 65535, 16618, -0.32, 3

依赖关系如此明显,我想分类应该很容易......

但结果很糟糕。我得到的准确度为 0.6 到 0.8。这绝对不适合我的应用程序。我知道我通常需要更多数据,但是当我至少可以拟合训练数据(不考虑潜在的过度拟合)时我会很高兴

这是代码:

import numpy as np
from scipy import optimize

from sklearn import cross_validation
from sklearn.metrics import accuracy_score
import math

class NN_1HL(object):

    def __init__(self, reg_lambda=0, epsilon_init=0.12, hidden_layer_size=25, opti_method='TNC', maxiter=500):
        self.reg_lambda = reg_lambda
        self.epsilon_init = epsilon_init
        self.hidden_layer_size = hidden_layer_size
        self.activation_func = self.sigmoid
        self.activation_func_prime = self.sigmoid_prime
        self.method = opti_method
        self.maxiter = maxiter

    def sigmoid(self, z):
        return 1 / (1 + np.exp(-z))

    def sigmoid_prime(self, z):
        sig = self.sigmoid(z)
        return sig * (1 - sig)

    def sumsqr(self, a):
        return np.sum(a ** 2)

    def rand_init(self, l_in, l_out):
        self.epsilon_init = (math.sqrt(6))/(math.sqrt(l_in + l_out))
        return np.random.rand(l_out, l_in + 1) * 2 * self.epsilon_init - self.epsilon_init

    def pack_thetas(self, t1, t2):
        return np.concatenate((t1.reshape(-1), t2.reshape(-1)))

    def unpack_thetas(self, thetas, input_layer_size, hidden_layer_size, num_labels):
        t1_start = 0
        t1_end = hidden_layer_size * (input_layer_size + 1)
        t1 = thetas[t1_start:t1_end].reshape((hidden_layer_size, input_layer_size + 1))
        t2 = thetas[t1_end:].reshape((num_labels, hidden_layer_size + 1))
        return t1, t2

    def _forward(self, X, t1, t2):
        m = X.shape[0]
        ones = None
        if len(X.shape) == 1:
            ones = np.array(1).reshape(1,)
        else:
            ones = np.ones(m).reshape(m,1)

        # Input layer
        a1 = np.hstack((ones, X))

        # Hidden Layer
        z2 = np.dot(t1, a1.T)
        a2 = self.activation_func(z2)
        a2 = np.hstack((ones, a2.T))

        # Output layer
        z3 = np.dot(t2, a2.T)
        a3 = self.activation_func(z3)
        return a1, z2, a2, z3, a3

    def function(self, thetas, input_layer_size, hidden_layer_size, num_labels, X, y, reg_lambda):
        t1, t2 = self.unpack_thetas(thetas, input_layer_size, hidden_layer_size, num_labels)

        m = X.shape[0]
        Y = np.eye(num_labels)[y]

        _, _, _, _, h = self._forward(X, t1, t2)
        costPositive = -Y * np.log(h).T
        costNegative = (1 - Y) * np.log(1 - h).T
        cost = costPositive - costNegative
        J = np.sum(cost) / m

        if reg_lambda != 0:
            t1f = t1[:, 1:]
            t2f = t2[:, 1:]
            reg = (self.reg_lambda / (2 * m)) * (self.sumsqr(t1f) + self.sumsqr(t2f))
            J = J + reg
        return J

    def function_prime(self, thetas, input_layer_size, hidden_layer_size, num_labels, X, y, reg_lambda):
        t1, t2 = self.unpack_thetas(thetas, input_layer_size, hidden_layer_size, num_labels)

        m = X.shape[0]
        t1f = t1[:, 1:]
        t2f = t2[:, 1:]
        Y = np.eye(num_labels)[y]

        Delta1, Delta2 = 0, 0
        for i, row in enumerate(X):
            a1, z2, a2, z3, a3 = self._forward(row, t1, t2)

            # Backprop
            d3 = a3 - Y[i, :].T
            d2 = np.dot(t2f.T, d3) * self.activation_func_prime(z2)

            Delta2 += np.dot(d3[np.newaxis].T, a2[np.newaxis])
            Delta1 += np.dot(d2[np.newaxis].T, a1[np.newaxis])

        Theta1_grad = (1 / m) * Delta1
        Theta2_grad = (1 / m) * Delta2

        if reg_lambda != 0:
            Theta1_grad[:, 1:] = Theta1_grad[:, 1:] + (reg_lambda / m) * t1f
            Theta2_grad[:, 1:] = Theta2_grad[:, 1:] + (reg_lambda / m) * t2f

        return self.pack_thetas(Theta1_grad, Theta2_grad)

    def fit(self, X, y):
        num_features = X.shape[0]
        input_layer_size = X.shape[1]
        num_labels = len(set(y))

        theta1_0 = self.rand_init(input_layer_size, self.hidden_layer_size)
        theta2_0 = self.rand_init(self.hidden_layer_size, num_labels)
        thetas0 = self.pack_thetas(theta1_0, theta2_0)

        options = {'maxiter': self.maxiter}
        _res = optimize.minimize(self.function, thetas0, jac=self.function_prime, method=self.method, 
                                 args=(input_layer_size, self.hidden_layer_size, num_labels, X, y, 0), options=options)

        self.t1, self.t2 = self.unpack_thetas(_res.x, input_layer_size, self.hidden_layer_size, num_labels)

        np.savetxt("weights_t1.txt", self.t1, newline="\n")
        np.savetxt("weights_t2.txt", self.t2, newline="\n")

    def predict(self, X):
        return self.predict_proba(X).argmax(0)

    def predict_proba(self, X):
        _, _, _, _, h = self._forward(X, self.t1, self.t2)
        return h


##################
# IR data        #
##################
values = np.loadtxt('infrared_data.txt', delimiter=', ', usecols=[0,1,2,3,4])

targets = np.loadtxt('infrared_data.txt', delimiter=', ', dtype=(int), usecols=[5])

X_train, X_test, y_train, y_test = cross_validation.train_test_split(values, targets, test_size=0.4)
nn = NN_1HL()
nn.fit(values, targets)
print("Accuracy of classification: "+str(accuracy_score(y_test, nn.predict(X_test))))

最佳答案

在给定的代码 scipy.optimize.minimize 中,给定函数的导数(雅可比矩阵),迭代地最小化函数。根据文档, use 可以为每次迭代后调用的函数指定回调参数 - 这将让您测量性能,尽管我不确定它是否会让您停止优化流程。

您列出的所有参数都是超参数,很难直接优化它们:

隐藏层中的神经元数量是离散值参数,因此无法通过梯度技术进行优化。此外,它会影响 NeuralNet 架构,因此在训练网络时无法对其进行优化。不过,您可以做的是使用一些更高级别的例程来搜索可能的选项,例如带有交叉验证的详尽网格搜索(例如查看 GridSearchCV )或用于超参数搜索的其他工具( hyperoptspearmintMOE 等) )。

学习率对于大多数可用的优化方法来说似乎都无法定制。但实际上,梯度下降中的学习率只是一种牛顿法,Hessian 方法通过 1/eta I 进行“近似”——对角矩阵,在主对角线上具有倒置的学习率。因此,您可以使用这种启发式尝试基于粗麻布的方法。

动量与正则化完全无关。这是一种优化技术,并且由于您使用 scipy 进行优化,因此不适合您。

关于python - scipy.optimize.minimize 在神经网络中的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27815580/

相关文章:

python - 如何安装 scipy misc 包

python - Python 中的对象回滚、写时复制、版本化代理等

python - 使用 Pandas 将数据框和其他数据保存在同一个 .csv 文件中

python - Django 表单操作属性无法正常工作

machine-learning - Isolation Forest 需要数据标准化吗?

python - 如何使用在不同项目中构建的分类模型对新文本进行分类?

numpy - 优化 Python KD 树搜索

php - 如何根据用户从网站输入的字段执行 Python 脚本

python - 支持向量机如何处理困惑的特征向量?

python - 确定 numpy 数组的 2 个(垂直或水平)相邻元素是否具有相同值的最快方法