作者 | Thomas Pernet 翻译 | 邓普斯·杰弗、涂世文、Disillusion
什么是线性分类器? 在有监督学习中,最主要的两种学习任务是 回归(regression) 和 分类(classification),而其中 线性回归 和 线性分类 最为常见。线性回归是预测某一个具体的值,而线性分类是数据所属类别进行预测。这里,我们主要关注线性分类问题。 一般来说,几乎 80% 机器学习任务可以看作是某种分类问题。分类,即给定一个输入的集合,分类器致力于预测每一个类别的概率。类别标记(也被称为 应变量或依赖变量)是一个离散的值,表示某个类别。 如果数据中的 Label 只有两个类别,那么就属于二分类问题,相应的分类器被称为 二分类器。 多分类器解决 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%的情况下是正确的。(也就是说,你的分类器可以直接判定都是不死亡,就可以实现非常高的准确度)
混淆矩阵: 评估分类器性能的更好方法是查看混淆矩阵。 
想象的混乱矩阵的准确度进行比较的当前和预测的分类器分类。组成:二进制混淆矩阵法: TP: 真正:正确预测为实际正的预测值 FP:预测值错误地预测了实际的正值。也就是说,预测为正值的负值 FN:假负:预测为负的正值 TN:真负:正确预测为实际负的预测值
从混淆矩阵可以很容易地比较实际标签结果和预测标签结果。
精确度和灵敏度 混淆矩阵可以很好地洞察真阳性和假阳性。在某些情况下,是一个更简洁的度量。 精确度 精准度显示正类的精度。它衡量了正类预测的正确程度。 
当分类器对所有正值进行完全分类时,最大得分为1。精确度本身并不是很有帮助,因为它忽略了负类。度量通常与召回成对出现。回忆也被称为敏感性或真阳性率。
灵敏性 灵敏度计算正确检测到的正类的比率。这个指标给出了模型识别正类的能力。 
对于本教程,我们将使用人口普查数据集。目的是使用人口普查数据集中的变量来预测收入水平。注意,收入是一个二元变量。 如果收入大于50K,值为1 如果收入小于50K,则为0。
这个变量是你的类别标签 该数据集包括八个分类变量: 工作场所 教育 婚姻的 职业 关系 种族 性别 国家
此外,六个连续变量: 年龄 FNLWgt 教育数字 资本收益 资本损失 小时\周
通过这个例子,您将了解如何用张量流估计训练线性分类器,以及如何提高准确度指标。 我们将按以下步骤进行: 第一步:导入数据 第二步:数据转换 第三步:训练分类器 第四步:改进模型 第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./ml/machine-learning-databases/adult/adult.data' PATH_test = 'https://archive.ics./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。 数据集的特征有两种格式: 整数 对象
每个特征都根据其类型在接下来的两个变量中列出。 ## 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。 例如,如果变量状态有三个不同的值: 丈夫 妻子 单身
然后三个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。 线性回归:LinearRegressor 线性分类: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%。仔细分析,你会发现预测和召回都很低。
第四部:模型改进 既然你有了一个基准模型,你可以尝试改进它,也就是说,提高精确度。在前面的教程中,您学习了如何通过交互项提高预测能力。在本教程中,您将通过向回归添加一个多项式项。 当数据存在非线性时,多项式回归是有用的。有两种方法可以捕获数据中的非线性。 增加多项式项 将连续变量变为离散变量
多项式项 从下图中,您可以看到什么是多项式回归。它是一个具有不同幂次的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) 平方变量在数据集中称为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%。 最后,您可以添加一个正则化项来防止过度拟合。
|