为什么这里的Lasso没有给我提供零系数?

我实现自己的深度特征选择版本的想法来自于这篇论文,http://link.springer.com/chapter/10.1007%2F978-3-319-16706-0_20

根据这篇论文,深度特征选择的基本思想是在任何全连接隐藏层之前添加一对一映射层,然后通过添加正则化项(无论是Lasso还是弹性网)来在输入层权重中产生零值。

我的问题是,尽管我似乎已经很好地实现了深度特征选择框架,但在使用numpy.rand.random(1000,50)生成的随机数据上测试时,初始权重并未得到任何零值。这是Lasso类正则化的常见现象吗?我是否需要调整我为这个框架使用的参数(甚至是更多的epochs)?还是我的代码有什么问题?

class DeepFeatureSelectionMLP:    def __init__(self, X, Y, hidden_dims=[100], epochs=1000,                 lambda1=0.001, lambda2=1.0, alpha1=0.001, alpha2=0.0, learning_rate=0.1):        # 初始化输入层        # 获取输入X的维度        n_sample, n_feat = X.shape        n_classes = len(np.unique(Y))        # One hot Y        one_hot_Y = np.zeros((len(Y), n_classes))        for i,j in enumerate(Y):            one_hot_Y[i][j] = 1        self.epochs = epochs        Y = one_hot_Y        # 存储原始值        self.X = X        self.Y = Y        # 创建两个未确定长度的变量        self.var_X = tf.placeholder(dtype=tf.float32, shape=[None, n_feat], name='x')        self.var_Y = tf.placeholder(dtype=tf.float32, shape=[None, n_classes], name='y')        self.input_layer = One2OneInputLayer(self.var_X)        self.hidden_layers = []        layer_input = self.input_layer.output        # 创建隐藏层        for dim in hidden_dims:            self.hidden_layers.append(DenseLayer(layer_input, dim))            layer_input = self.hidden_layers[-1].output        # 最终分类层,传递变量Y        self.softmax_layer = SoftmaxLayer(self.hidden_layers[-1].output, n_classes, self.var_Y)        n_hidden = len(hidden_dims)        # 对输入层系数的正则化项         self.L1_input = tf.reduce_sum(tf.abs(self.input_layer.w))        self.L2_input = tf.nn.l2_loss(self.input_layer.w)        # 对隐藏层权重的正则化项                L1s = []        L2_sqrs = []        for i in xrange(n_hidden):            L1s.append(tf.reduce_sum(tf.abs(self.hidden_layers[i].w)))            L2_sqrs.append(tf.nn.l2_loss(self.hidden_layers[i].w))        L1s.append(tf.reduce_sum(tf.abs(self.softmax_layer.w)))        L2_sqrs.append(tf.nn.l2_loss(self.softmax_layer.w))        self.L1 = tf.add_n(L1s)        self.L2_sqr = tf.add_n(L2_sqrs)        # 包含两个正则化项的成本        self.cost = self.softmax_layer.cost \                    + lambda1*(1.0-lambda2)*0.5*self.L2_input + lambda1*lambda2*self.L1_input \                    + alpha1*(1.0-alpha2)*0.5 * self.L2_sqr + alpha1*alpha2*self.L1        self.optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(self.cost)        self.y = self.softmax_layer.y    def train(self, batch_size=100):        sess = tf.Session()        sess.run(tf.initialize_all_variables())        for i in xrange(self.epochs):            x_batch, y_batch = get_batch(self.X, self.Y, batch_size)            sess.run(self.optimizer, feed_dict={self.var_X: x_batch, self.var_Y: y_batch})            if (i + 1) % 50 == 0:                l = sess.run(self.cost, feed_dict={self.var_X: x_batch, self.var_Y: y_batch})                print('epoch {0}: global loss = {1}'.format(i, l))                self.selected_w = sess.run(self.input_layer.w)                print(self.selected_w)class One2OneInputLayer(object):    # 一对一映射!    def __init__(self, input):        """            输入的第二个维度,            对于每个输入,每行是一个样本            每列是一个特征,由于             这是一对一映射,n_in等于             特征的数量        """        n_in = input.get_shape()[1].value        self.input = input        # 初始化输入层的权重        w = tf.Variable(tf.zeros([n_in,]), name='w')        self.w = w        self.output = self.w * self.input        self.params = [w]class DenseLayer(object):    # 标准密集层    def __init__(self, input, n_out, activation='sigmoid'):        """            输入的第二个维度,            对于每个输入,每行是一个样本            每列是一个特征,由于             这是一对一映射,n_in等于             特征的数量            n_out定义了隐藏层中有多少节点        """        n_in = input.get_shape()[1].value        self.input = input        # 初始化输入层的权重        w = tf.Variable(tf.ones([n_in, n_out]), name='w')        b = tf.Variable(tf.ones([n_out]), name='b')        output = tf.add(tf.matmul(input, w), b)        output = activate(output, activation)        self.w = w        self.b = b        self.output = output        self.params = [w]class SoftmaxLayer(object):    def __init__(self, input, n_out, y):        """            输入的第二个维度,            对于每个输入,每行是一个样本            每列是一个特征,由于             这是一对一映射,n_in等于             特征的数量            n_out定义了隐藏层中有多少节点        """        n_in = input.get_shape()[1].value        self.input = input        # 初始化该层的权重和偏置        w = tf.Variable(tf.random_normal([n_in, n_out]), name='w')        b = tf.Variable(tf.random_normal([n_out]), name='b')        pred = tf.add(tf.matmul(input, w), b)        cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(pred, y))        self.y = y        self.w = w        self.b = b        self.cost = cost        self.params= [w]

回答:

像Adam这样的梯度下降算法在使用L1正则化时不会给出精确的零值。相反,像ftrlproximal adagrad这样的算法可以给你精确的零值。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注