特征预处理

import numpy as np
import pandas as pd

import tensorflow as tf

from tensorflow import feature_column
from tensorflow.keras import layers
from sklearn.model_selection import train_test_split

数据

URL = 'https://storage.googleapis.com/applied-dl/heart.csv'
dataframe = pd.read_csv(URL)
train, test = train_test_split(dataframe, test_size=0.2)
train, val = train_test_split(train, test_size=0.2)

使用tf.data创建输入流水线

# 一种从 Pandas Dataframe 创建 tf.data 数据集的实用程序方法(utility method)
def df_to_dataset(dataframe, shuffle=True, batch_size=32):
  dataframe = dataframe.copy()
  labels = dataframe.pop('target')
  ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels))
  if shuffle:
    ds = ds.shuffle(buffer_size=len(dataframe))
  ds = ds.batch(batch_size)
  return ds

特征列

TensorFlow提供了多种特征列在feature_column模块下,下面创建常用的几类特征列,应演示特征列如何转换dataframe中的列。

from tensorflow import  feature_column

创建一个特征列,并转换一批次数据的一个实用程序方法:

# 使用该批次数据演示几种特征列
example_batch = next(iter(train_ds))[0]

def demo(feature_column):
	feature_layer = layers.DenseFeatures(feature_column)
	print(feature_layer(example_batch).numpy())

1. 分桶列

数值型离散化,例如:将年龄分成几个桶buckets

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

2. 分类列

在此数据集中,thal用字符串表示(如:‘fixed’, ‘normal’, 或 ‘reversible’)。我们无法直接将字符串提供给模型,相反,我们必须首先将它们映射到数值。分类词汇列(categorical vocabulary columns)提供了一种用one-hot向量表示字符串的方法。词汇表可以用categorical_column_with_vocabulary_list作为list传递,或者用categorical_column_with_vocabulary_file从文件中加载

thal = feature_column.categorical_column_with_vocabulary_list('thal',['fixed', 'normal', 'reversible'])
thal_one_hot = feature_column.indicator_column(thal)
demo(thal_one_hot)

3.1 嵌入列

假设我们不是只有几个可能的字符串,而是每个类别有数千(或更多)值。由于多种原因,随着类别数量的增加,使用one-hot编码训练神经网络变得不可行。我们可以使用嵌入例来克服此限制。嵌入列(embedding column)将数据表示为一个低维度稠密向量,而非多维的one-hot向量,该低维密集向量可以包含任何数,而非0或1。嵌入的大小是必须调整的参数。

# 当分类列具有许多可能的值时,最好使用嵌入列
thal_embedding = feature_column.embedding_column(thal, dimension=8)
demo(thal_embedding)

3.2 经过哈希处理的特征列

表示具有大量数值的分类列的另一种方法是使用categorical_column_with_hash_bucket。该特征列计算输入的一个哈希值,然后选择一个hash_bucket_size分桶来编码字符串。使用此列时,您不需要提供词汇表,并且可以选择使hash_buckets的数量远远小于实际类别的数量以节省空间。
**注:**该技术的一个重要缺点是可能存在冲突,不同的字符串被映射到同一个范围。实际上,无论如何,经过哈希处理的特征列对某些数据集都是有效。

thal_hashed = feature_column.categorical_column_with_hash_bucket('thal',hash_bucket_size = 1000)

demo(feature_column.indicator_column(thal_hashed))

4. 组合的特征列

将多种特征组合到一个特征中,称为特征组合(feature crosses),它让模型能够为每种特征组合学习单独的权重。此外,我们将创建一个age和thal组合的新特征。请注意,crossed_column 不会构建所有可能组合的完整列表(可能非常大)。相反,它由hashed_column支持,可以选择表的大小。

crossed_feature = feature_column.crossed_column([age_buckets,thal],hash_bucket_size=1000)
demo(feature_column,indicator_column(crossed_feature))

选择要使用的列,训练模型

feature_columns = []
# 数值列
for header in ['age','tresbps','chol','thalach','oldpeak','ca']:
	feature_columns.append(feature_column.numeric_column(header))

# 分桶列
age_buckets = feature_column.bucketized_column(age, boundaries = [18,25,30,35,40,45,50,55,60,65])
feature_column.append(age_buckets)

# 分类列
thal =feature_column.categorical_column_with_vocabulary_list('thal',['fixed','normal','reversible'])
thal_one_hot = feature_column.indicator_column(thal)
feature_columns.append(thal_one_hot)

#嵌入列
thal_embedding = feature_column.embedding_column(thal,dimension =8)
feature_columns.append(thal_embedding)

# 组合列
crossed_feature = feature_column.crossed_column([age_buckets,thal],hash_bucket_size = 1000)
crossed_feature = feature_column.indicator_column(crossed_feature)
feature_columns.append(crossed_feature)

建立一个新的特征层

上面我们已经定义了特征列,需要使用密集特征(DenseFeatures)层将特征列输入到Keras模型中。

feature_layer = tf.keras.layers.DenseFeatures(feature_columns)

训练数据集

batch_size = 32
train_ds = df_to_dataset(train, batch_size= batch_size)

val_ds = df_to_dataset(val, shuffle = False, batch_size=batch_size)
test_ds = df_to_dataset(test, shuffle = False, batch_size= batch_size)

创建、编译、训练模型

model = tf.keras.Sequential([
	feature_layer,
	layers.Dense(128, activation = 'relu'),
	layers.Dense(128, activation = 'relu'),
	layers.Dense(1, activation ='sigmoid')
])

model.compile(
	optimizer='adam',
	loss='binary_crossentropy',
	metrics=['accuracy'],
	run_early=True)
model.fit(train_ds, validation_data= val_ds,epochs =5)
上一篇:element 表格方法cell-style改变单元格样式


下一篇:1.29我的第十二篇