打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
一文带你读懂线性分类器

作者 | Thomas Pernet

翻译 | 邓普斯·杰弗、涂世文、Disillusion


  什么是线性分类器?

在有监督学习中,最主要的两种学习任务是 回归(regression) 和 分类(classification),而其中 线性回归 和 线性分类 最为常见。线性回归是预测某一个具体的值,而线性分类是数据所属类别进行预测。这里,我们主要关注线性分类问题。

一般来说,几乎 80% 机器学习任务可以看作是某种分类问题。分类,即给定一个输入的集合,分类器致力于预测每一个类别的概率。类别标记(也被称为 应变量或依赖变量)是一个离散的值,表示某个类别。

  1. 如果数据中的 Label 只有两个类别,那么就属于二分类问题,相应的分类器被称为 二分类器。

  2. 多分类器解决 Label 种类多于两种类别的分类问题。

譬如,预测顾客是否会进行二次购买便是一个典型的二分类问题。而识别图片中出现动物则是属于多分类问题,因为实际情况中动物有很多种。

本文的理论部分主要关注于二分类问题。未来我们也会推出关于多分类的内容,敬请期待!


  二分类器是如何工作的?

在前面的教程中你已经了解到函数由两类变量组成,一个应变量和一组特征(自变量)。在线性回归中,应变量是一个没有范围的实数。主要目标是通过最小化均方误差来预测其值。

对于二分类任务,标签可以有两个可能的整数值。在大多数情况下,要么是[0,1]要么是[1,2]。

例如,如果目标是预测客户是否会购买产品。标签可为如下:

  • Y = 1(客户购买了产品)

  • Y = 0 (客户没有购买产品)

该模型使用特征X将每个客户分类到他最有可能的所属类别,即是潜在购买者,或否。

成功的概率用逻辑回归计算。该算法将根据特征X计算出一个概率,并在该概率大于50%时预测成功。概率的算式如下:


θ是权重的集合,x是特征,b是偏差 

该函数可进一步分为两部分:  

  • 线性模型  

  • 逻辑函数


线性模型

你已经熟悉了计算权重的方法。权重计算使用点积:θ^ Tx + b

Y是所有特征x_i的线性函数。如果模型没有特征,则预测结果为偏差b。  

权值表示特征x_i与标签y之间相关性的方向。正相关增加了正类的概率,而负相关使概率更接近于0(即负类)。

线性模型只返回实数,与区间[0,1]的概率测度不一致。因此需要逻辑函数将线性模型输出转换为概率。


逻辑函数

逻辑函数,亦称sigmoid函数,为s形,且输出总是在0和1之间。  

将线性回归的输出代入sigmoid函数是很容易的。它产生一个概率在0和1之间的新数字。

分类器可以将概率转化为类

  • 0到0.49之间的值分到0类

  • 从0.5到1之间的值分到1类


  如何度量显性分类器的性能?

准确度:

分类器的整体性能是用准确度量来衡量的。准确度收集所有正确值除以观测总数。例如,精度值为80%意味着模型在80%的情况下是正确的。

您可以注意到这个度量的一个缺点,特别是对于不平衡样本分类情况。当每组的观测次数不相等时,就会出现不平衡数据集。比如说,你试图用logistics函数来分类一个罕见的事件。假设分类器试图估计疾病后患者的死亡。在数据中,5%的病人去世了。您可以训练分类器来预测死亡人数,并使用准确度量来评估性能。如果分类器预测整个数据集的死亡为0,那么则95%的情况下是正确的。(也就是说,你的分类器可以直接判定都是不死亡,就可以实现非常高的准确度)


混淆矩阵:

评估分类器性能的更好方法是查看混淆矩阵。

想象的混乱矩阵的准确度进行比较的当前和预测的分类器分类。组成:二进制混淆矩阵法:

  1. TP: 真正:正确预测为实际正的预测值

  2. FP:预测值错误地预测了实际的正值。也就是说,预测为正值的负值

  3. FN:假负:预测为负的正值

  4. TN:真负:正确预测为实际负的预测值

从混淆矩阵可以很容易地比较实际标签结果和预测标签结果。


精确度和灵敏度

混淆矩阵可以很好地洞察真阳性和假阳性。在某些情况下,是一个更简洁的度量。

精确度

精准度显示正类的精度。它衡量了正类预测的正确程度。

当分类器对所有正值进行完全分类时,最大得分为1。精确度本身并不是很有帮助,因为它忽略了负类。度量通常与召回成对出现。回忆也被称为敏感性或真阳性率。

灵敏性
灵敏度计算正确检测到的正类的比率。这个指标给出了模型识别正类的能力。


  tensorflow实现线性分类器

对于本教程,我们将使用人口普查数据集。目的是使用人口普查数据集中的变量来预测收入水平。注意,收入是一个二元变量。

  1. 如果收入大于50K,值为1

  2. 如果收入小于50K,则为0。

这个变量是你的类别标签

该数据集包括八个分类变量:

  1. 工作场所

  2. 教育

  3. 婚姻的

  4. 职业

  5. 关系

  6. 种族

  7. 性别

  8. 国家

此外,六个连续变量:

  1. 年龄

  2. FNLWgt

  3. 教育数字

  4. 资本收益

  5. 资本损失

  6. 小时\周

通过这个例子,您将了解如何用张量流估计训练线性分类器,以及如何提高准确度指标。

我们将按以下步骤进行:

第一步:导入数据

第二步:数据转换

第三步:训练分类器

第四步:改进模型

第5步:超参数:Lasso & Ridge


开始分布介绍:

步骤1:导入数据

首先导入教程中使用的库。

导入TensorFlow as tf \ import  pandas as pd

接下来,从UCI存档导入数据并定义列名称。您将使用列来命名pandas dataframe。

请注意,您将使用Pandas dataframe来训练分类器。

import pandas as pd
import tensorflow as tf
## Define path data
COLUMNS = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital',
          'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss',
          'hours_week', 'native_country', 'label']
PATH = 'https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data'
PATH_test = 'https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.test'

/Users/Thomas/anaconda3/envs/hello-tf/lib/python3.6/importlib/_bootstrap.py:219: RuntimeWarning: compiletime version 3.5 of module 'tensorflow.python.framework.fast_tensor_util' does not match runtime version 3.6
 return f(*args, **kwds)

在线存储的数据已经在训练组和测试组之间进行了划分。

df_train = pd.read_csv(PATH, skipinitialspace=True, names = COLUMNS, index_col=False)
df_test = pd.read_csv(PATH_test,skiprows = 1, skipinitialspace=True, names = COLUMNS, index_col=False)

训练数据集合包含32561组数据,测试数据集中包含16281组数据;

print(df_train.shape, df_test.shape)
print(df_train.dtypes)

(32561, 15) (16281, 15)
age                int64
workclass         object
fnlwgt             int64
education         object
education_num      int64
marital           object
occupation        object
relationship      object
race              object
sex               object
capital_gain       int64
capital_loss       int64
hours_week         int64
native_country    object
label             object
dtype: object

TensorFlow需要一个布尔值来训练分类器。您需要将值从字符串转换为整数。标签存储为一个对象,但是,您需要将其转换为一个数值。下面的代码创建一个字典,其中包含要转换的值,并在列项上循环。请注意,您执行此操作两次,一次针对训练数据集,一次用于测试数据集;

label = {'<=50K': 0,'>50K': 1}
df_train.label = [label[item] for item in df_train.label]
label_t = {'<=50K.': 0,'>50K.': 1}
df_test.label = [label_t[item] for item in df_test.label]

训练数据中,50K以下收入24720人,以上收入7841人。测试集的比率几乎相同。有关更多信息,请参阅本教程中的方面。

print(df_train['label'].value_counts())
### The model will be correct in atleast 70% of the case
print(df_test['label'].value_counts())
## Unbalanced label
print(df_train.dtypes)

0    24720
1     7841
Name: label, dtype: int64
0    12435
1     3846
Name: label, dtype: int64
age                int64
workclass         object
fnlwgt             int64
education         object
education_num      int64
marital           object
occupation        object
relationship      object
race              object
sex               object
capital_gain       int64
capital_loss       int64
hours_week         int64
native_country    object
label              int64
dtype: object


第二步:数据转化

在用TensorFlow训练线性分类器之前,需要执行几个步骤。您需要准备要包含在模型中的特征。在基准回归中,您将使用原始数据而不应用任何转换。

估计器需要有一个特征列表来训练模型。因此,列的数据需要转换为张量。

一个好的实践是根据特征的类型定义两个特征列表,然后将它们传递到估计器的特征列中。

您将从转换连续特性开始,然后用分类数据定义一个bucket。

数据集的特征有两种格式:

  1. 整数

  2. 对象

每个特征都根据其类型在接下来的两个变量中列出。

## Add features to the bucket:
### Define continuous list
CONTI_FEATURES  = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week']
### Define the categorical list
CATE_FEATURES = ['workclass', 'education', 'marital', 'occupation', 'relationship', 'race', 'sex', 'native_country']

Feature_column 装配了一个对象numeric_column,以帮助将连续变量转换为张量。在下面的代码中,您可以将CONTI_FEATURES 特征中的所有变量转换为具有数值的张量。这对于构建模型是必需的。所有的自变量都需要转换成合适的张量类型。

下面我们编写一个代码,让您了解feature_column.numeric_column 后面发生了什么。我们将打印转换后的值用于解释,因此不需要理解Python代码。您可以参考官方文档了解这些代码。

def print_transformation(feature = 'age', continuous = True, size = 2):
   #X = fc.numeric_column(feature)
   ## Create feature name
   feature_names = [
   feature]

## Create dict with the data
   d = dict(zip(feature_names, [df_train[feature]]))
   ## Convert age
   if continuous == True:
       c = tf.feature_column.numeric_column(feature)
       feature_columns = [c]
   else:
       c = tf.feature_column.categorical_column_with_hash_bucket(feature, hash_bucket_size=size)
       c_indicator = tf.feature_column.indicator_column(c)
       feature_columns = [c_indicator]
   
## Use input_layer to print the value
   input_layer = tf.feature_column.input_layer(
       features=d,
       feature_columns=feature_columns
       )
   ## Create lookup table
   zero = tf.constant(0, dtype=tf.float32)
   where = tf.not_equal(input_layer, zero)
   ## Return lookup tble
   indices = tf.where(where)
   values = tf.gather_nd(input_layer, indices)
   ## Initiate graph
   sess = tf.Session()
   ## Print value
   print(sess.run(input_layer))

print_transformation(feature = 'age', continuous = True)

[[39.]
[50.]
[38.]
...
[58.]
[22.]
[52.]]

这些值与df_train中的值完全相同

continuous_features = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES]

根据TensorFlow文档,有不同的方法来转换分类数据。如果某个功能的词汇表是已知的,并且没有足够的值,则可以使用“词汇表”创建“分类”列用categorical_column_with_vocabulary_list。它将为所有唯一词汇表分配一个ID。

例如,如果变量状态有三个不同的值:

  1. 丈夫

  2. 妻子

  3. 单身

然后三个ID将被属性化。例如,丈夫将拥有ID 1,妻子ID 2等等。

为了便于说明,可以使用此代码在TensorFlow中将对象变量转换为分类列。

特征性别只能有两个价值:男性或女性。当我们转换特征性时,TensorFlow将创建两个新列,一个用于男性,一个用于女性。如果性别等于男性,那么新的列“男性”将等于1,而“女性”将等于0。此示例显示在下表中:

tensorflow中:

print_transformation(feature = “sex”, continuous = False, size = 2)

relationship = tf.feature_column.categorical_column_with_vocabulary_list(
   'relationship', [
       'Husband', 'Not-in-family', 'Wife', 'Own-child', 'Unmarried',
       'Other-relative'])

下面,我们添加了python代码来打印编码。同样,您不需要理解代码,目的是看到转换

但是,转换数据的一种更快的方法是使用方法:categorical_column_with_hash_bucket。改变稀疏矩阵中的字符串变量是有用的。稀疏矩阵是一个基本上为零的矩阵。您只需要指定存储桶的数量和键列。桶数是TensorFlow可以创建的最大组数。键列只是要转换的列的名称。

在下面的代码中,您将在所有分类功能上创建一个循环。

categorical_features = [tf.feature_column.categorical_column_with_hash_bucket(k, hash_bucket_size=1000) for k in CATE_FEATURES]


第三步:训练分类器

tensorflow目前为线性回归和线性分类提供了一个estimator。

  1. 线性回归:LinearRegressor

  2. 线性分类:LinearClassifier

线性分类器的语法与线性回归教程中的语法相同,除了一个参数n_class。您需要定义特征列、模型目录,并与线性回归器进行比较;您已经定义了类的数量。对于逻辑回归,类的数目等于2。

模型将计算包含在continuous_features and categorical_features 的特征列的权重。

model = tf.estimator.LinearClassifier(
   n_classes = 2,
   model_dir='ongoing/train',
   feature_columns=categorical_features+ continuous_features)
INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train', '_tf_random_seed': Non

既然定义了分类器,就可以创建输入函数。该方法与线性回归器教程中的方法相同。在这里,您使用128的批量大小,然后对数据进行无序处理。

FEATURES = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country']
LABEL= 'label'
def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True):
   return tf.estimator.inputs.pandas_input_fn(
      x=pd.DataFrame({k: data_set[k].values for k in FEATURES}),
      y = pd.Series(data_set[LABEL].values),
      batch_size=n_batch,  
      num_epochs=num_epochs,
      shuffle=shuffle)

您可以使用线性估计所需的参数创建一个函数,即epoch数、batches数和shuffle处理数据集或注释。由于使用pandas方法将数据传递到模型中,因此需要将x变量定义为pandas dataframe。请注意,您将循环访问存储在FEATURES中的所有数据。

让我们用对象model.train来训练模型。您可以使用先前定义的函数向模型提供适当的值。请注意,您将批大小设置为128,并且将epoch数设置为none。模型将经过一千多步的训练。

model.train(input_fn=get_input_fn(df_train,
                                     num_epochs=None,
                                     n_batch = 128,
                                     shuffle=False),
                                     steps=1000)
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 0 into ongoing/train/model.ckpt.
INFO:tensorflow:loss = 88.722855, step = 1
INFO:tensorflow:global_step/sec: 95.9134
INFO:tensorflow:loss = 52583.64, step = 101 (1.044 sec)
INFO:tensorflow:global_step/sec: 167.726
INFO:tensorflow:loss = 25203.816, step = 201 (0.596 sec)
INFO:tensorflow:global_step/sec: 162.827
INFO:tensorflow:loss = 54924.312, step = 301 (0.614 sec)
INFO:tensorflow:global_step/sec: 226.156
INFO:tensorflow:loss = 68509.31, step = 401 (0.443 sec)
INFO:tensorflow:global_step/sec: 143.237
INFO:tensorflow:loss = 9151.754, step = 501 (0.701 sec)
INFO:tensorflow:global_step/sec: 140.458
INFO:tensorflow:loss = 34576.06, step = 601 (0.710 sec)
INFO:tensorflow:global_step/sec: 131.307
INFO:tensorflow:loss = 36047.117, step = 701 (0.764 sec)
INFO:tensorflow:global_step/sec: 150.417
INFO:tensorflow:loss = 22608.148, step = 801 (0.665 sec)
INFO:tensorflow:global_step/sec: 162.276
INFO:tensorflow:loss = 22201.918, step = 901 (0.615 sec)
INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train/model.ckpt.
INFO:tensorflow:Loss for final step: 5444.363.

<tensorflow.python.estimator.canned.linear.LinearClassifier at 0xb202e4668>

请注意,损失随后在最后100个步骤中减少,即从901减少到1000。

一千次迭代后的最终损失是5444。您可以在测试集中估计您的模型并查看性能。要评估模型的性能,需要使用对象evaluate。您向模型提供测试集,并将epoch的数目设置为1,即数据将只输入模型一次。

model.evaluate(input_fn=get_input_fn(df_test,
                                     num_epochs=1,
                                     n_batch = 128,
                                     shuffle=False),
                                     steps=1000)
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to 'careful_interpolation' instead.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to 'careful_interpolation' instead.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-08-29-19:10:30
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from ongoing/train/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Evaluation [100/1000]
INFO:tensorflow:Finished evaluation at 2018-08-29-19:10:33
INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.7615626, accuracy_baseline = 0.76377374, auc = 0.63300294, auc_precision_recall = 0.50891197, average_loss = 47.12155, global_step = 1000, label/mean = 0.23622628, loss = 5993.6406, precision = 0.49401596, prediction/mean = 0.18454961, recall = 0.38637546
INFO:tensorflow:Saving 'checkpoint_path' summary for global step 1000: on

{'accuracy': 0.7615626,
'accuracy_baseline': 0.76377374,
'auc': 0.63300294,
'auc_precision_recall': 0.50891197,
'average_loss': 47.12155,
'label/mean': 0.23622628,
'loss': 5993.6406,
'precision': 0.49401596,
'prediction/mean': 0.18454961,
'recall': 0.38637546,
'global_step': 1000}

TensorFlow返回理论部分中学习的所有度量指标。不出所料,由于标签不平衡,精度很高。实际上,模型的性能比随机猜测略好。假设该模型预测所有收入低于50K的家庭,那么该模型的准确率为70%。仔细分析,你会发现预测和召回都很低。


第四部:模型改进

既然你有了一个基准模型,你可以尝试改进它,也就是说,提高精确度。在前面的教程中,您学习了如何通过交互项提高预测能力。在本教程中,您将通过向回归添加一个多项式项。

当数据存在非线性时,多项式回归是有用的。有两种方法可以捕获数据中的非线性。

  1. 增加多项式项

  2. 将连续变量变为离散变量

多项式项

从下图中,您可以看到什么是多项式回归。它是一个具有不同幂次的x变量的方程。二次多项式回归有两个变量,x和x的平方。三度有三个变量,x、$x^ 2、\和\x^ 3$

下面,我们构造了一个有两个变量的图,x和y。很明显,这种关系不是线性的。如果我们添加线性回归,我们可以看到模型无法捕获模式(左图)。
现在,从下面的图片看左边的图片,我们在回归中添加了五项。

这个模型现在可以更好地捕捉模式。这是多项式回归的强大。

让我们回到我们的例子。年龄与收入没有线性关系。由于儿童或年轻人不工作,早年的收入可能接近零。然后它在工作年龄上增加,在退休期间减少。它通常是一个倒U形。捕获这种模式的一种方法是在回归中添加一个二次项。

让我们看看它是否提高了精确度。
您需要将这个新特性添加到数据集和连续特性列表中。

在训练和测试数据集中添加新的变量,这样编写函数就更方便了。

def square_var(df_t, df_te, var_name = 'age'):
   df_t['new'] = df_t[var_name].pow(2)
   df_te['new'] = df_te[var_name].pow(2)
   return df_t, df_te

函数有3个参数:

  • 定义训练集

  • 定义测试集

  • var_name='age':定义要转换的变量

您可以使用对象POW(2)来调整可变年龄。请注意,新变量名为“new”

现在编写了函数square_var,就可以创建新的数据集。

df_train_new, df_test_new = square_var(df_train, df_test, var_name = 'age')

如下所示,数据集多了一个新的特征:

print(df_train_new.shape, df_test_new.shape)

(32561, 16) (16281, 16)

平方变量在数据集中称为new。您需要将其添加到连续功能列表中。

CONTI_FEATURES_NEW  = ['age', 'fnlwgt','capital_gain', 'education_num', 'capital_loss', 'hours_week', 'new']
continuous_features_new = [tf.feature_column.numeric_column(k) for k in CONTI_FEATURES_NEW]

请注意,更改了图形的目录。不能在同一目录中训练不同的模型。这意味着,你需要改变参数 model_dir。如果不这样做,TensorFlow将抛出一个错误。

model_1 = tf.estimator.LinearClassifier(
   model_dir='ongoing/train1',
   feature_columns=categorical_features+ continuous_features_new)
INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train1', '_tf_random_seed': No

FEATURES_NEW = ['age','workclass', 'fnlwgt', 'education', 'education_num', 'marital', 'occupation', 'relationship', 'race', 'sex', 'capital_gain', 'capital_loss', 'hours_week', 'native_country', 'new']
def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True):
   return tf.estimator.inputs.pandas_input_fn(
      x=pd.DataFrame({k: data_set[k].values for k in FEATURES_NEW}),
      y = pd.Series(data_set[LABEL].values),
      batch_size=n_batch,  
      num_epochs=num_epochs,
      shuffle=shuffle)

现在分类器是用新的数据集设计的,那么就可以训练和评估模型了。

model_1.train(input_fn=get_input_fn(df_train,
                                     num_epochs=None,
                                     n_batch = 128,
                                     shuffle=False),
                                     steps=1000)
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 0 into ongoing/train1/model.ckpt.
INFO:tensorflow:loss = 88.722855, step = 1
INFO:tensorflow:global_step/sec: 65.4699
INFO:tensorflow:loss = 70077.66, step = 101 (1.533 sec)
INFO:tensorflow:global_step/sec: 166.451
INFO:tensorflow:loss = 49522.082, step = 201 (0.599 sec)
INFO:tensorflow:global_step/sec: 172.15
INFO:tensorflow:loss = 107120.57, step = 301 (0.577 sec)
INFO:tensorflow:global_step/sec: 135.673
INFO:tensorflow:loss = 12814.152, step = 401 (0.741 sec)
INFO:tensorflow:global_step/sec: 147.318
INFO:tensorflow:loss = 19573.898, step = 501 (0.675 sec)
INFO:tensorflow:global_step/sec: 205.764
INFO:tensorflow:loss = 26381.986, step = 601 (0.486 sec)
INFO:tensorflow:global_step/sec: 188.238
INFO:tensorflow:loss = 23417.719, step = 701 (0.531 sec)
INFO:tensorflow:global_step/sec: 226.805
INFO:tensorflow:loss = 23946.049, step = 801 (0.441 sec)
INFO:tensorflow:global_step/sec: 183.742
INFO:tensorflow:loss = 3309.5786, step = 901 (0.544 sec)
INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train1/model.ckpt.
INFO:tensorflow:Loss for final step: 28861.898.

<tensorflow.python.estimator.canned.linear.LinearClassifier at 0xb20308ba8>

model_1.evaluate(input_fn=get_input_fn(df_test_new,
                                     num_epochs=1,
                                     n_batch = 128,
                                     shuffle=False),
                                     steps=1000)
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to 'careful_interpolation' instead.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to 'careful_interpolation' instead.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-08-29-19:10:49
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from ongoing/train1/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Evaluation [100/1000]
INFO:tensorflow:Finished evaluation at 2018-08-29-19:10:51
INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.7944229, accuracy_baseline = 0.76377374, auc = 0.6093755, auc_precision_recall = 0.54885805, average_loss = 111.0046, global_step = 1000, label/mean = 0.23622628, loss = 14119.265, precision = 0.6682401, prediction/mean = 0.09116262, recall = 0.2576703
INFO:tensorflow:Saving 'checkpoint_path' summary for global step 1000:

{'accuracy': 0.7944229,
'accuracy_baseline': 0.76377374,
'auc': 0.6093755,
'auc_precision_recall': 0.54885805,
'average_loss': 111.0046,
'label/mean': 0.23622628,
'loss': 14119.265,
'precision': 0.6682401,
'prediction/mean': 0.09116262,
'recall': 0.2576703,
'global_step': 1000}

平方变量将精度从0.76提高到0.79。让我们看看是否可以通过将bucketization和interaction项组合在一起做得更好。


  Bucketization and interaction

正如您之前看到的,线性分类器无法正确捕获年龄收入模式。这是因为它为每个特性学习一个权重。为了使分类器更容易,您可以做的一件事是将特征存储起来。Bucketing根据数字特征所处的范围将其转换为若干特定特征,这些新特征中的每一个都指示一个人的年龄是否在该范围内。
利用这些新特性,线性模型可以通过学习每个桶的不同权重来捕获关系。
在TensorFlow中,它是用bucketized_column完成的。您需要在边界中添加值的范围。

age = tf.feature_column.numeric_column('age')
age_buckets = tf.feature_column.bucketized_column(
   age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65])

你已经知道年龄与收入是非线性的。另一种改进模型的方法是通过interaction。在TensorFlow这个词中,它是特征交叉。特征交叉是创建现有特征组合的新特征的一种方法,这对于无法对特征之间的交互进行建模的线性分类器很有帮助。

你可以用教育这样的另一个特征来划分年龄。也就是说,有些群体的收入可能很高,而其他群体的收入可能很低(例如博士生)。

education_x_occupation = [tf.feature_column.crossed_column(
   ['education', 'occupation'], hash_bucket_size=1000)]
age_buckets_x_education_x_occupation = [tf.feature_column.crossed_column(
   [age_buckets, 'education', 'occupation'], hash_bucket_size=1000)]

要创建交叉特征列,请使用带变量的crossed_column在括号中交叉。散列桶大小表示最大的交叉可能性。要在变量之间创建交互(至少有一个变量需要分类),可以使用tf.feature_column.crossed_column。要使用此对象,需要在方括号中添加要交叉的变量和第二个参数bucket size。bucket size是变量中可能的最大组数。这里你把它设为1000,因为你不知道年龄组的确切数目。

在将其添加到功能列之前需要平方。您还可以将新特性添加到特性列,并准备estimator。

base_columns = [
   age_buckets,
]
model_imp = tf.estimator.LinearClassifier(
   model_dir='ongoing/train3',
   feature_columns=categorical_features+base_columns+education_x_occupation+

INFO:tensorflow:Using default config.
INFO:tensorflow:Using config: {'_model_dir': 'ongoing/train3', '_tf_random_seed': None, '_save_summary_steps': 100, '_save_checkpoints_steps': None, '_save_checkpoints_secs': 600, '_session_config': None, '_keep_checkpoint_max': 5, '_keep_checkpoint_every_n_hours': 10000, '_log_step_count_steps': 100, '_train_distribute': None, '_device_fn': None, '_service': None, '_cluster_spec': <tensorflow.python.training.server_lib.ClusterSpec object at 0xb20ef8550>, '_task_type': 'worker', '_task_id': 0, '_global_id_in_cluster': 0, '_master': '', '_evaluation_master': '', '_is_chief': True, '_num_ps_replicas': 0, '_num_worker_replicas': 1}

FEATURES_imp = ['age','workclass', 'education', 'education_num', 'marital',
               'occupation', 'relationship', 'race', 'sex', 'native_country', 'new']

def get_input_fn(data_set, num_epochs=None, n_batch = 128, shuffle=True):
   return tf.estimator.inputs.pandas_input_fn(
      x=pd.DataFrame({k: data_set[k].values for k in FEATURES_imp}),
      y = pd.Series(data_set[LABEL].values),
      batch_size=n_batch,  
      num_epochs=num_epochs,
      shuffle=shuffle)

您已经准备好评估新模型,看看它是否提高了精度。

model_imp.train(input_fn=get_input_fn(df_train_new,
                                     num_epochs=None,
                                     n_batch = 128,
                                     shuffle=False),
                                     steps=1000)
INFO:tensorflow:Calling model_fn.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Create CheckpointSaverHook.
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Saving checkpoints for 0 into ongoing/train3/model.ckpt.
INFO:tensorflow:loss = 88.722855, step = 1
INFO:tensorflow:global_step/sec: 110.894
INFO:tensorflow:loss = 50.334488, step = 101 (0.905 sec)
INFO:tensorflow:global_step/sec: 204.578
INFO:tensorflow:loss = 56.153225, step = 201 (0.489 sec)
INFO:tensorflow:global_step/sec: 201.008
INFO:tensorflow:loss = 45.792007, step = 301 (0.495 sec)
INFO:tensorflow:global_step/sec: 145.813
INFO:tensorflow:loss = 37.485672, step = 401 (0.688 sec)
INFO:tensorflow:global_step/sec: 255.157
INFO:tensorflow:loss = 56.48449, step = 501 (0.390 sec)
INFO:tensorflow:global_step/sec: 196.914
INFO:tensorflow:loss = 32.528934, step = 601 (0.507 sec)
INFO:tensorflow:global_step/sec: 190.965
INFO:tensorflow:loss = 37.438057, step = 701 (0.529 sec)
INFO:tensorflow:global_step/sec: 162.964
INFO:tensorflow:loss = 61.1075, step = 801 (0.610 sec)
INFO:tensorflow:global_step/sec: 202.747
INFO:tensorflow:loss = 44.69645, step = 901 (0.494 sec)
INFO:tensorflow:Saving checkpoints for 1000 into ongoing/train3/model.ckpt.
INFO:tensorflow:Loss for final step: 44.18133.

<tensorflow.python.estimator.canned.linear.LinearClassifier at 0xb21883e80>

model_imp.evaluate(input_fn=get_input_fn(df_test_new,
                                     num_epochs=1,
                                     n_batch = 128,
                                     shuffle=False),
                                     steps=1000)
INFO:tensorflow:Calling model_fn.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to 'careful_interpolation' instead.
WARNING:tensorflow:Trapezoidal rule is known to produce incorrect PR-AUCs; please switch to 'careful_interpolation' instead.
INFO:tensorflow:Done calling model_fn.
INFO:tensorflow:Starting evaluation at 2018-08-29-19:11:05
INFO:tensorflow:Graph was finalized.
INFO:tensorflow:Restoring parameters from ongoing/train3/model.ckpt-1000
INFO:tensorflow:Running local_init_op.
INFO:tensorflow:Done running local_init_op.
INFO:tensorflow:Evaluation [100/1000]
INFO:tensorflow:Finished evaluation at 2018-08-29-19:11:06
INFO:tensorflow:Saving dict for global step 1000: accuracy = 0.8358209, accuracy_baseline = 0.76377374, auc = 0.88401634, auc_precision_recall = 0.69599575, average_loss = 0.35122654, global_step = 1000, label/mean = 0.23622628, loss = 44.67437, precision = 0.68986726, prediction/mean = 0.23320661, recall = 0.55408216
INFO:tensorflow:Saving 'checkpoint_path' summary for global step 1000: ongoing/trai

{'accuracy': 0.8358209,
'accuracy_baseline': 0.76377374,
'auc': 0.88401634,
'auc_precision_recall': 0.69599575,
'average_loss': 0.35122654,
'label/mean': 0.23622628,
'loss': 44.67437,
'precision': 0.68986726,
'prediction/mean': 0.23320661,
'recall': 0.55408216,
'global_step': 1000}

新的准确度是83.58%。它比以前的模型高4%。
最后,您可以添加一个正则化项来防止过度拟合。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
R语言线性判别分析(LDA),二次判别分析(QDA)和正则判别分析(RDA)
只需十四步:从零开始掌握Python机器学习
如何用一个Python示例入门TensorFlow?
谷歌教你学 AI-第六讲深度神经网络
机器学习零基础?手把手教你用TensorFlow搭建图像识别系统(三)| 干货
这4个最流行的深度学习框架,你用过几个?
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服