> For the complete documentation index, see [llms.txt](https://kerasnoone.gitbook.io/garnet/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kerasnoone.gitbook.io/garnet/gong-cheng-zhan/wang-luo-kuang-jia/tensorflow/featurecolumns-jian-yao-shuo-ming/column-lei-xing.md).

# Column类型

## Column的两种类型

`tf.feature_columns`中定义了两大类特征列(Feature column), 一类是**DenseColumn**, 另一类是**CategoricalColumn**. 两者有以下的区别:

* DenseColumn可以生成dense tensor, 而CategoricalColumn生成的是SparseTensor
* 由于深度学习模型的**输入必须是Dense类型的输入**, 因此由多个DenseColumn经过转换后生成的输入是Dense Tensor, 可以直接继续搭建模型
  * 但如果投入模型的columns中, 有CategoricalColumn, 而它只能生成SparseTensor, 因此是无法直接转换为Dense Tensor继续构建模型的
  * 需要使用**indicator\_column**进行one-hot/multi-hot转化为dense vector, 或**embedding\_column**将类映射为dense vector后, 才能与其他DenseColumn共同生成dense tensor作为模型的输入

![](https://1942165044-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MI7KRyeBH5dlW-CkUtn%2Fsync%2Fbda47aba88262377624a604f9c2fe635e53390e1.png?generation=1619136961187173\&alt=media)

## Column的声明方法

在进行特征工程时, 会先将数据集中所有用到的列, 根据各自的类型, 声明为**原始特征**. 然后对这些原始特征进行转化, 交叉等操作, 得到新的特征. 最后从原始特征和处理得到的新特征中挑选出优质特征, 给模型使用.

因此从特征工程的角度, column分为两类: **原始特征**和**加工特征**.

## 原始特征类型

原始特征指的是直接声明的特征, 往往直接对应着原始数据集中的某一列. 声明原始特征, 只需要为这个特征起一个名字, 有些特征还需要提供一些参数.

按特征是**连续型**, 还是**类别型**划分, `tf.feature_columns`中有以下几种原始特征.

### 连续型

#### numeric\_column

**返回类型**: DenseColumn

**作用**: 生成原始连续数字特征. 例如用户年龄, 用户具体收入等特征.

**入参**

* key: 特征名
* shape: 对应的Tensor的shape(省略batch\_size维度), 默认为`(1,)`
* default\_value: 对应的输入数据中如果有缺失, 使用这个值补充, 默认为`None`, 此时如果数据集中有缺失的情况, 会抛出异常
* dtype: 数值类型, 默认为`float32`
* normalizer\_fn: 归一化函数, 如果不为`None`, 每个输入值都会经过这个函数得到归一化后的值再使用. 例如白化操作`lambda x: (x - 3.0) / 4.2`

### 类别型

#### categorical\_column\_with\_identity

**返回类型**: CategoricalColumn(IdentityCategoricalColumn)

**作用**: 生成类别特征, 生成的方式直接指定有多少个桶, 每个桶就是一个类别. 假设指定的桶的数量为$$N$$, 则输入必须$$\[0, 1, \cdots, N - 1)$$中的整数, 直接指明属于哪一类(哪一个桶)

相当于为每个桶都分配了一个ID, 且这些桶的ID从0开始, 逐1递增.

一般应用有种类编号的特征上.

**入参**

* key: 特征名
* num\_buckets: 类别/桶的数量, 出入参都在`[0, num_buckets)`范围内
* default\_value: 对应的输入数据中如果有缺失, 使用这个值补充, 如果使用这个参数, 赋值必须在\[0, num\_buckets)之间. 默认为`None`, 此时如果数据集中有缺失的情况, 会抛出异常

#### categorical\_column\_with\_hash\_bucket

**返回类型**: CategoricalColumn(HashedCategoricalColumn)

**作用**: 生成类别特征, 生成的方式与`categorical_column_with_identity`有些类似, 但不同点为:

* 同样是指定桶的数量, `categorical_column_with_identity`中要求输入必须是数字, 且范围在`[0, num_buckets)`范围内
* `categorical_column_with_hash_bucket`的输入可以是包括字符串在内的任意类型(只要所有的输入保持一种类型), 然后使用哈希函数将每个输入映射到一个桶中, 也就找到了对应的类别
* 对应的特征, 一般来说类别的数量远大于桶的数量

**入参**

* key: 特征名
* hash\_bucket\_size: 类别/桶的数量
* dtype: 输入数据的类型. 默认是`string`, 只支持string和int两种类型

#### categorical\_column\_with\_vocabulary\_list

**返回类型**: CategoricalColumn(VocabularyListCategoricalColumn)

**作用**: 生成类别特征, 生成方式为指定该特征的词典, 词典包含该特征所有可能的取值

**入参**

* key: 特征名
* vocabulary\_list: 特征词典
* dtype: 入参的数据类型, 只接受string和int两种类型. 默认为`None`, 从`vocabulary_list`中判断类型
* default\_value: 对于OOV(out-of-vocabulary)的情况, 赋值一个整数ID, 值必须在`[0, len(vocabulary_list))`之间. 默认为-1, 不能与`num_oov_buckets`参数同时使用
* num\_oov\_buckets: 对于OOV(out-of-vocabulary)的情况, 随机分配到`[len(vocabulary_list), len(vocabulary_list)+num_oov_buckets)`之间的整数ID. 默认为0, 不使用额外的桶来装OOV的情况. 如果使用该参数, 必须制定一个正整数, 且不能于`default_value`参数同时使用

## 加工特征类型

与上面的原始特征不同, **加工特征**是需要以**其他特征**为入参, 对其他特征进行处理, 得到新的特征.

**按输入特征类型分类**:

* 输入是数值型: bucketzied\_column
* 输入是类别型: indicator\_column, embedding\_column, crossed\_column

**按输入的特征数量分类**:

* 输入一个特征: bucketzied\_column, indicator\_column, embedding\_column
* 输入多个特征: crossed\_column

### bucketzied\_column

**返回类型**: DenseColumn + CategoricalColumn(BucketizedColumn)

**作用**: 输入一个数值型特征, 并给出分桶方案, 将原始的数值型特征, 按照自身数值和分桶方案, 映射到不同的桶中, 完成离散化的, 也即**one-hot**操作, 得到dense one-hot vector

**入参**:

* source\_column: 需要分桶的`numeric_column`特征
* boundaries: 分桶方案, 是一个数值列表
  * 例如`boundaries=[0., 1., 2.]`, 将会产生`(-inf, 0.), [0., 1.), [1., 2.), [2., +inf)`这4个分桶

### indicator\_column

**返回类型**: DenseColumn(IndicatorColumn)

**作用**: 接受一个`CategoricalColumn`特征, 对其进行`one-hot`或`multi-hot`操作, 转换成dense vector

对于各个`CategoricalColumn`, 由于不能直接投入到模型中使用, 可以经过该方法转换成dense vector, 从而可以与其他dense vector拼接在一起, 给模型使用

**入参**:

* categorical\_column: 输入的`CategoricalColumn`

### embedding\_column

**返回类型**: DenseColumn(EmbeddingColumn)
