[tensorflow] softmax函数解析

def softmax(logits, axis=None, name=None, dim=None):
  """Computes softmax activations.

  This function performs the equivalent of

      softmax = tf.exp(logits) / tf.reduce_sum(tf.exp(logits), axis)

  Args:
    logits: A non-empty `Tensor`. Must be one of the following types: `half`,
      `float32`, `float64`.
    axis: The dimension softmax would be performed on. The default is -1 which
      indicates the last dimension.
    name: A name for the operation (optional).
    dim: Deprecated alias for `axis`.

  Returns:
    A `Tensor`. Has the same type and shape as `logits`.

  Raises:
    InvalidArgumentError: if `logits` is empty or `axis` is beyond the last
      dimension of `logits`.
  """
  axis = deprecation.deprecated_argument_lookup("axis", axis, "dim", dim)
  if axis is None:
    axis = -1
  return _softmax(logits, gen_nn_ops.softmax, axis, name)

softmax函数的返回结果和输入的tensor有相同的shape,既然没有改变tensor的形状,那么softmax究竟对tensor做了什么?

答案就是softmax会以某一个轴的下标为索引,对这一轴上其他维度的值进行 激活 + 归一化处理

一般来说,这个索引轴都是表示类别的那个维度(tf.nn.softmax中默认为axis=-1,也就是最后一个维度)

举例:

def softmax(X, theta = 1.0, axis = None):
    """
    Compute the softmax of each element along an axis of X.

    Parameters
    ----------
    X: ND-Array. Probably should be floats.
    theta (optional): float parameter, used as a multiplier
        prior to exponentiation. Default = 1.0
    axis (optional): axis to compute values along. Default is the
        first non-singleton axis.

    Returns an array the same size as X. The result will sum to 1
    along the specified axis.
    """

    # make X at least 2d
    y = np.atleast_2d(X)

    # find axis
    if axis is None:
        axis = next(j[0] for j in enumerate(y.shape) if j[1] > 1)

    # multiply y against the theta parameter,
    y = y * float(theta)

    # subtract the max for numerical stability
    y = y - np.expand_dims(np.max(y, axis = axis), axis)

    # exponentiate y
    y = np.exp(y)

    # take the sum along the specified axis
    ax_sum = np.expand_dims(np.sum(y, axis = axis), axis)

    # finally: divide elementwise
    p = y / ax_sum

    # flatten if X was 1D
    if len(X.shape) == 1: p = p.flatten()

    return p
c = np.random.randn(2,3)
print(c)
# 假设第0维是类别,一共有里两种类别
cc = softmax(c,axis=0)
# 假设最后一维是类别,一共有3种类别
ccc = softmax(c,axis=-1)
print(cc)
print(ccc)

结果:

c:
[[-1.30022268  0.59127472  1.21384177]
 [ 0.1981082  -0.83686108 -1.54785864]]
cc:
[[0.1826746  0.80661068 0.94057075]
 [0.8173254  0.19338932 0.05942925]]
ccc:
[[0.0500392  0.33172426 0.61823654]
 [0.65371718 0.23222472 0.1140581 ]]

可以看到,对axis=0的轴做softmax时,输出结果在axis=0轴上和为1(eg: 0.1826746+0.8173254),同理在axis=1轴上做的话结果的axis=1轴和也为1(eg: 0.0500392+0.33172426+0.61823654)。

这些值是怎么得到的呢?

以cc为例(沿着axis=0做softmax):

cc[0,0] = 0.1826746 = \frac{e^{cc[0,0]}}{\sum_{k=0}^{1}e^{cc[k,0]}}

其中e^{cc[0,0]}属于激活操作,\frac{1}{\sum_{k=0}^{1}e^{cc[k,0]}}属于归一化操作。

以ccc为例(沿着axis=1做softmax):

ccc[0,0] = 0.0500392 = \frac{e^{ccc[0,0]}}{\sum_{k=0}^{2}e^{cc[0,k]}}

知道了计算方法,现在我们再来讨论一下这些值的实际意义:

cc[0,0]实际上表示这样一种概率: P( label = 0 |  value = [-1.30022268  0.1981082] = c[*,0] ) = 0.1826746

cc[1,0]实际上表示这样一种概率: P( label = 1 |  value = [-1.30022268  0.1981082] = c[*,0] ) = 0.8173254

ccc[0,0]实际上表示这样一种概率: P( label = 0 |  value = [-1.30022268  0.59127472  1.21384177] = c[0]) = 0.0500392

ccc[0,1]实际上表示这样一种概率: P( label = 1 |  value = [-1.30022268  0.59127472  1.21384177] = c[0]) = 0.33172426

ccc[0,2]实际上表示这样一种概率: P( label = 2 |  value = [-1.30022268  0.59127472  1.21384177] = c[0]) = 0.61823654

将他们扩展到更多维的情况:假设c是一个[batch_size , timesteps, categories]的三维tensor

output = tf.nn.softmax(c,axis=-1)

那么 output[1, 2, 3] 则表示 P(label =3 | value = c[1,2] ) 

 

参考:

  1. http://ufldl.stanford.edu/wiki/index.php/Softmax%E5%9B%9E%E5%BD%92
  2. http://www.tensorfly.cn/tfdoc/api_docs/python/nn.html#softmax
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
人脸识别是一个较为复杂的任务,涉及到很多技术和算法。基于TensorFlow的人脸识别代码通常会使用深度学习框架来实现,同时需要使用一些经典的人脸识别算法,如人脸检测、特征提取、人脸匹配等。 以下是一个使用TensorFlow实现的基于神经网络的人脸识别代码示例: ```python import tensorflow as tf import numpy as np # 加载数据 def load_data(): # 加载数据集 X_train, y_train, X_test, y_test = ... # 对数据进行预处理 X_train = np.array(X_train).reshape(-1, 28, 28, 1) X_test = np.array(X_test).reshape(-1, 28, 28, 1) y_train = tf.keras.utils.to_categorical(y_train, num_classes=10) y_test = tf.keras.utils.to_categorical(y_test, num_classes=10) # 返回处理后的数据集 return X_train, y_train, X_test, y_test # 定义模型 def create_model(): model = tf.keras.Sequential([ # 卷积层 tf.keras.layers.Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(28, 28, 1)), tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), tf.keras.layers.Flatten(), # 全连接层 tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dropout(0.5), tf.keras.layers.Dense(10, activation='softmax') ]) # 定义优化器和损失函数 model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy']) return model # 训练模型 def train(X_train, y_train, X_test, y_test): model = create_model() model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test)) # 测试模型 def test(X_test, y_test): model = create_model() model.load_weights('model.h5') model.evaluate(X_test, y_test) # 加载数据 X_train, y_train, X_test, y_test = load_data() # 训练模型 train(X_train, y_train, X_test, y_test) # 保存模型 model.save_weights('model.h5') # 测试模型 test(X_test, y_test) ``` 上述代码实现了一个简单的手写数字识别模型,其中使用了一个包含卷积层、池化层和全连接层的神经网络模型。在训练过程中使用了Adam优化器和交叉熵损失函数。最终测试集上的识别精度可以达到99%。 当然,实际上的人脸识别应用要更加复杂,需要使用更加高级的神经网络模型和人脸检测算法,以及更多的预处理和后处理技术。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值