tensorflow處理結構化數據


一、泰坦尼克數據集

首先從csv讀取數據

import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import tensorflow as tf
from tensorflow.keras import layers,models
'''
#==================================================================
# 一,構建數據管道
#==================================================================
'''

dftrain_raw = pd.read_csv("./data/titanic/train.csv")
dftest_raw = pd.read_csv("./data/titanic/test.csv")

dfraw = pd.concat([dftrain_raw,dftest_raw],axis=0)

def prepare_dfdata(dfraw):
    dfdata = dfraw.copy()
    dfdata.columns = [x.lower() for x in dfdata.columns]
    dfdata = dfdata.rename(columns={'survived':'label'})
    dfdata = dfdata.drop(['passengerid','name'],axis = 1)
    for col,dtype in dict(dfdata.dtypes).items():
        # 判斷是否包含缺失值
        if dfdata[col].hasnans:
            # 添加標識是否缺失列
            dfdata[col + '_nan'] = pd.isna(dfdata[col]).astype('int32')
            # 填充,如果是數字,那么就添加這一列的平均值,否則空着
            if dtype not in [np.object,np.str,np.unicode]:
                dfdata[col].fillna(dfdata[col].mean(),inplace = True)
            else:
                dfdata[col].fillna('',inplace = True)
    return(dfdata)

dfdata = prepare_dfdata(dfraw)
dftrain = dfdata.iloc[0:len(dftrain_raw),:]
dftest = dfdata.iloc[len(dftrain_raw):,:]

# 從 dataframe 導入數據 
def df_to_dataset(df, shuffle=True, batch_size=4):
    dfdata = df.copy()
    if 'label' not in dfdata.columns:
        ds = tf.data.Dataset.from_tensor_slices(dfdata.to_dict(orient = 'list'))
    else: 
        labels = dfdata.pop('label')
        ds = tf.data.Dataset.from_tensor_slices((dfdata.to_dict(orient = 'list'), labels))  
    if shuffle:
        ds = ds.shuffle(buffer_size=len(dfdata))
    ds = ds.batch(batch_size)
    return ds

ds_train = df_to_dataset(dftrain)
ds_test = df_to_dataset(dftest)


tensorflow只能處理數值類型的數據,如何將原始數據轉換為神經網絡的輸入格式:使用特征列模塊 tf.feature_column,在輸入數據和模型之間搭建橋梁

特征列完成以下等功能:

  1. 類別特征轉換為ont-hot編碼特征
  2. 連續特征轉換為分桶特征
  3. 特征組合

二、定義特征列

2.1 數值特征使用 tf.feature_column.numeric_column得到數值列。

feature_columns = []
for col in ['age','fare','parch','sibsp'] + [
    c for c in dfdata.columns if c.endswith('_nan')]:
    feature_columns.append(tf.feature_column.numeric_column(col))

2.2 比如年齡數據,按區間進行划分,使用tf.feature_column.bucketized_column 得到分桶列。
不直接將一個數值直接傳給模型,而是根據數值范圍將其值分為不同的 categories。
此時,10個年齡間隔得到ont-hot列表長度為11,小於18歲的轉換為[1,0,0,0,0,0,0,0,0,0,0]

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])
feature_columns.append(age_buckets)

2.3 類別特征,使用tf.feature_column.categorical_column_with_vocabulary_list 轉換為 one-hot編碼

sex = tf.feature_column.indicator_column(
      tf.feature_column.categorical_column_with_vocabulary_list(
      key='sex',vocabulary_list=["male", "female"]))
feature_columns.append(sex)

2.4 當類別很多或者我們不知道有多少類的時候,我們不能一個一個的列出來,這時候就可以使用hash_bucket,第二個參數是我們想把這些數據分成多少類,
這個類別數和真實的類別數不一定是一樣的,我們自己設置划分為多少類即可。
使用tf.feature_column.categorical_column_with_has_bucket 對 ticket列進行轉換。

ticket = tf.feature_column.indicator_column(
     tf.feature_column.categorical_column_with_hash_bucket('ticket',3))
feature_columns.append(ticket)

2.5 當類別很多的時候,借由lookup table的方式找尋對應的feature vector來表示。tf.feature_column.embedding_column
嵌入列可以看成keras.layers.Embedding層

cabin = tf.feature_column.embedding_column(
    tf.feature_column.categorical_column_with_hash_bucket('cabin',32),2)
feature_columns.append(cabin)

2.6 多個特征組合為一個特征,組合列。tf.feature_column.crossed_column

pclass_cate = tf.feature_column.categorical_column_with_vocabulary_list(
          key='pclass',vocabulary_list=[1,2,3])

crossed_feature = tf.feature_column.indicator_column(
    tf.feature_column.crossed_column([age_buckets, pclass_cate],hash_bucket_size=15))

feature_columns.append(crossed_feature)

ps:此時 feature_columns 僅僅保存了一些特征列,需要在定義模型的時候把這些特征列作為輸入層放到 tf.keras.layers.DenseFeatures

三、定義&訓練模型

通過 layers.DenseFeatures(feature_columns) 完成了原始特征到模型輸入特征的轉換。
fit 階段 之間輸入 tf.data.Dataset 數據。

tf.keras.backend.clear_session()
model = tf.keras.Sequential([
  layers.DenseFeatures(feature_columns), #將特征列放入到tf.keras.layers.DenseFeatures中!!!
  layers.Dense(64, activation='relu'),
  layers.Dense(64, activation='relu'),
  layers.Dense(1, activation='sigmoid')
])

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

history = model.fit(ds_train,
          validation_data=ds_test,
          epochs=10)

總結:對於結構化輸入數據,使用特征列tf.feature_column模塊的各個方法進行處理得到多個特征列,作為layers.DenseFeatures()層的輸入。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM