python - 使用 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)
解决方案
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]))
推荐阅读
- scala - scalaz.io : 展平 IO[Throwable, Seq[IO[Nothing, String]]]
- javascript - 重定向到另一个网页时,该功能会不断重复
- c++ - Unordered_map gets empty after inserting an element, what am I doing wrong?
- javascript - ng serve 和 ng build 在风格上给出了不同的结果
- mongodb - 聚合选择中的计数结果
- oauth - 与活动目录集成
- java - 如何理解 Java 中比较器引发的顺序?
- java - 具有不同颜色状态栏的两个活动
- django - 如何将 URL 添加到通用 ListView
- c# - 如何在触发属性中基于 dotnet 核心的 Azure 函数中从 settings.json 读取配置值