首页 > 解决方案 > 使用 softmax 激活的二元分类总是输出 1

问题描述

抱歉问题的质量,但这里是初学者,我只是用泰坦尼克号数据集试试运气,但它总是预测乘客死亡。我尝试解释下面的代码:

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns


import tensorflow as tf

from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras import losses
from tensorflow.keras.layers.experimental import preprocessing

import os

加载数据集

dataset_dir = os.path.join(os.getcwd(), 'titanic')
train_url = os.path.join(dataset_dir, 'train.csv')
test_url = os.path.join(dataset_dir, 'test.csv')


raw_train_dataset = pd.read_csv(train_url)
raw_test_dataset = pd.read_csv(test_url)


train = raw_train_dataset.copy()
test = raw_test_dataset.copy()

删除一些列,我可能在这里错了

train = train.drop(['Cabin','Name','Ticket'], 1)
test = test.drop(['Cabin','Name','Ticket'], 1)

热矢量

train = pd.get_dummies(train, prefix='', prefix_sep='')
test = pd.get_dummies(test, prefix='', prefix_sep='')

训练标签

train_predict = train.pop('Survived')

用平均值填充空年龄

train['Age'].fillna((train['Age'].mean()), inplace=True)
test['Age'].fillna((train['Age'].mean()), inplace=True)

删除空列

test = test.dropna()
train = train.dropna()

创建标准化层

normalizer = preprocessing.Normalization()
normalizer.adapt(np.array(train))

创建 dnn ,我在这里错了吗

model = keras.Sequential([
      normalizer,
      layers.Dense(64, activation='relu'),
      layers.Dropout(0.2),
      layers.Dense(1)
  ])



model.compile(loss=losses.BinaryCrossentropy(from_logits=True),
              optimizer='adam',
              metrics=tf.metrics.BinaryAccuracy(threshold=0.0))


history = model.fit(
    train, train_predict,
    validation_split=0.2,
     epochs=30)

这在每种情况下都显示为 1,但在训练时我仍然获得 85% 的准确率,我不需要问题的完整解决方案(我想自己尝试),而只是我被卡住的部分

result = tf.nn.softmax(model(train))
print(result)

标签: pythontensorflowmachine-learningkerasdeep-learning

解决方案


tf.nn.softmax将始终返回一个数组sum=1。由于您的输出是 1 个值(您的最终/输出层上有一个单元),因此 softmax 操作会将这个值转换为 1。

for value in [.2, .999, .0001, 100., -100.]:
    print(tf.nn.softmax([value]))
tf.Tensor([1.], shape=(1,), dtype=float32)
tf.Tensor([1.], shape=(1,), dtype=float32)
tf.Tensor([1.], shape=(1,), dtype=float32)
tf.Tensor([1.], shape=(1,), dtype=float32)
tf.Tensor([1.], shape=(1,), dtype=float32)

您正在寻找的是tf.nn.sigmoid

for value in [.2, .999, .0001, 100., -100.]:
    print(tf.nn.sigmoid([value]))
tf.Tensor([0.549834], shape=(1,), dtype=float32)
tf.Tensor([0.7308619], shape=(1,), dtype=float32)
tf.Tensor([0.500025], shape=(1,), dtype=float32)
tf.Tensor([1.], shape=(1,), dtype=float32)
tf.Tensor([0.], shape=(1,), dtype=float32)

losses.BinaryCrossentropy(from_logits=True)就像 sigmoid 交叉熵。

如果要将值四舍五入以获得 0 或 1,请使用tf.round

tf.round(tf.nn.sigmoid([.1]))

推荐阅读