类型数据
特征里经常会有非数值类型的,比如某个用户去看电影,他留下的非数值特征可能有:星期几去的,几月份,几点,是不是节假日,当天天气等.这些数据属于类型数据(categorical data),比如:
星期几:一二三四五六七
月份:一到十二月
当天天气:晴,雨,阴,雪.
以前一直以为在构建特征时碰到这种类型数据,用一位数字表示就好,比如某个样本的特征是(2, 12 , 22 , 0, 1)表示星期二,十二月,22点,非节假日,晴天.但最近看书才知道不是这样,应该用一种称作二元编码的方法.
二元编码
首先统计某个类型数据一共有几类,比如星期几共有7种类型.二元编码就是只再对应的位置上为1,其它全是0.比如星期一对应(1,0,0,0,0,0,0).不过不是非要按照顺序来,比如星期三不一定是(0,0,1,0,0,0,0).每种特征按照这种方式转换,最后拼起来.
想了想这么做确实有道理,参数多了,对每个特征的每种情况都训练了一个或者多个参数.如果写成(2, 12 , 22 , 0, 1)参数就太少.
例子
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 
 | 
 
 
 
 
 
 def get_mapping(dataset, idx):
 '''dataset是所有数据,统计各维特征并编号
 '''
 featset = set()
 for data in dataset:
 featset.add(data[idx])
 return dict(zip(featset, range(0, len(featset))))
 
 
 mappings = [get_mapping(dataset, idx) for idx in range(0, 3)]
 
 feature_len = sum(map(len, mappings))
 
 def get_one_hot_feature(data, mappings, feature_len):
 '''data是一条数据
 '''
 feature_vec = np.zeros(feature_len)
 idx = 0
 step = 0
 for feature in data:
 feature_vec[step + mappings[idx][feature]] = 1.0
 step += len(mappings[idx])
 idx += 1
 return feature_vec
 
 all_one_hot_feature = map(lambda data: get_one_hot_feature(data, mappings, feature_len), dataset)
 
 |