机器学习之特征工程

机器学习之特征工程

特征工程是机器学习的基础,也是机器学习取得好的效果的前提,简单来说特征工程是将原始数据转换为更好的代表预测模型的潜在问题的特征的过程,从而提高对未知数据的预测准确性。

1.特征抽取

特征抽取是对文本等数据进行特征值化,这里将会用到机器学习库sklearn,特征抽取的算法函数在sklearn.feature_extraction包下,主要的特征抽取有以下几种形式:

1.字典特征抽取
sklearn.feature_extraction.DictVectorizer
流程:

  • 实例化类DictVectorizer
  • 调用fit_transform方法输入数据并转换,转换为one-hot编码
from sklearn.feature_extraction import DictVectorizer

def dictvec():
   """
   字典数据抽取
   :return: None
   """
   # 实例化
   dict = DictVectorizer(sparse=False)

   # 调用fit_transform,
   data = dict.fit_transform([{'city': '北京','temperature': 100}, {'city': '上海','temperature':60}, {'city': '深圳','temperature': 30}])
   #['city=上海', 'city=北京', 'city=深圳', 'temperature']
   print(dict.get_feature_names())
   print(dict.inverse_transform(data))
   """
   [[  0.   1.   0. 100.]
    [  1.   0.   0.  60.]
    [  0.   0.   1.  30.]]
    转换为了one-hot编码
   """
   print(data)
   return None
   
if __name__ == "__main__":
    dictvec()

运行结果:

['city=上海', 'city=北京', 'city=深圳', 'temperature']
[{'city=北京': 1.0, 'temperature': 100.0}, {'city=上海': 1.0, 'temperature': 60.0}, {'city=深圳': 1.0, 'temperature': 30.0}]
[[  0.   1.   0. 100.]
 [  1.   0.   0.  60.]
 [  0.   0.   1.  30.]]

[ 0. 1. 0. 100.]对应的就是[‘city=上海’, ‘city=北京’, ‘city=深圳’, ‘temperature’],表示北京的temperature为100

2.文本特征抽取CountVectorizer
流程:

  • 实例化类sklearn.feature_extraction.text.CountVectorizer
  • 调用fit_transform方法输入数据并转换,转换为one-hot编码
from sklearn.feature_extraction.text import CountVectorizer

def countvec():
    """
    对文本进行特征值化
    :return: None
    """
    cv = CountVectorizer()
    data = cv.fit_transform(["人生 苦短,我 喜欢 python", "人生漫长,不用 python"])
    #['python', '不用', '人生', '人生漫长', '喜欢', '苦短']
    print(cv.get_feature_names())
    """
    [[1 0 1 0 1 1]
     [1 1 0 1 0 0]]
    """
    print(data.toarray())
    return None
    
if __name__ == "__main__":
    countvec()

运行结果

['python', '不用', '人生', '人生漫长', '喜欢', '苦短']
[[1 0 1 0 1 1]
 [1 1 0 1 0 0]]

需要注意的是CountVectorizer并不会对中文文本进行分词处理,需要自己使用jieba分词后再进行特征值化,如下:

import jieba
def cutword():

    con1 = jieba.cut("今天很残酷,明天更残酷,后天很美好,但绝大部分是死在明天晚上,所以每个人不要放弃今天。")

    con2 = jieba.cut("我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。")

    con3 = jieba.cut("如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。")

    # 转换成列表
    content1 = list(con1)
    content2 = list(con2)
    content3 = list(con3)

    # 吧列表转换成字符串
    c1 = ' '.join(content1)
    c2 = ' '.join(content2)
    c3 = ' '.join(content3)

    return c1, c2, c3
def hanzivec():
    """
    中文特征值化
    :return: None
    """
    c1, c2, c3 = cutword()
    print(c1, c2, c3)
    cv = CountVectorizer()
    data = cv.fit_transform([c1, c2, c3])
    print(cv.get_feature_names())
    print(data.toarray())
    return None
    
if __name__ == "__main__":
    hanzivec()

运行结果:

今天 很 残酷 , 明天 更 残酷 , 后天 很 美好 , 但 绝大部分 是 死 在 明天 晚上 , 所以 每个 人 不要 放弃 今天 。 我们 看到 的 从 很 远 星系 来 的 光是在 几百万年 之前 发出 的 , 这样 当 我们 看到 宇宙 时 , 我们 是 在 看 它 的 过去 。 如果 只用 一种 方式 了解 某样 事物 , 你 就 不会 真正 了解 它 。 了解 事物 真正 含义 的 秘密 取决于 如何 将 其 与 我们 所 了解 的 事物 相 联系 。
['一种', '不会', '不要', '之前', '了解', '事物', '今天', '光是在', '几百万年', '发出', '取决于', '只用', '后天', '含义', '如何', '如果', '宇宙', '我们', '所以', '放弃', '方式', '明天', '星系', '晚上', '某样', '残酷', '每个', '看到', '真正', '秘密', '绝大部分', '美好', '联系', '过去', '这样']
[[0 0 1 0 0 0 2 0 0 0 0 0 1 0 0 0 0 0 1 1 0 2 0 1 0 2 1 0 0 0 1 1 0 0 0]
 [0 0 0 1 0 0 0 1 1 1 0 0 0 0 0 0 1 3 0 0 0 0 1 0 0 0 0 2 0 0 0 0 0 1 1]
 [1 1 0 0 4 3 0 0 0 0 1 1 0 1 1 1 0 1 0 0 1 0 0 0 1 0 0 0 2 1 0 0 1 0 0]]

3.tf与idf, tf*idf为重要程度
TF-IDF思想:如果某个词或短语在一篇文章中出现的频率高,并且在其他文章中很少出现,则认为该词或短语具有很好的类别区分能力,适合用于分类。

  • tf:term frequency:词出现的次数
  • idf: inverse document frequency 逆文档频率,计算公式是log(总文档数量/该词出现的文档数量)
from sklearn.feature_extraction.text import TfidfVectorizer


def tfidfvec():
    """
    中文特征值化
    :return: None
    """
    c1, c2, c3 = cutword()
    print(c1, c2, c3)
    tf = TfidfVectorizer()
    data = tf.fit_transform([c1, c2, c3])
    print(tf.get_feature_names())
    print(data.toarray())
    return None
    

运行结果:

今天 很 残酷 , 明天 更 残酷 , 后天 很 美好 , 但 绝大部分 是 死 在 明天 晚上 , 所以 每个 人 不要 放弃 今天 。 我们 看到 的 从 很 远 星系 来 的 光是在 几百万年 之前 发出 的 , 这样 当 我们 看到 宇宙 时 , 我们 是 在 看 它 的 过去 。 如果 只用 一种 方式 了解 某样 事物 , 你 就 不会 真正 了解 它 。 了解 事物 真正 含义 的 秘密 取决于 如何 将 其 与 我们 所 了解 的 事物 相 联系 。
['一种', '不会', '不要', '之前', '了解', '事物', '今天', '光是在', '几百万年', '发出', '取决于', '只用', '后天', '含义', '如何', '如果', '宇宙', '我们', '所以', '放弃', '方式', '明天', '星系', '晚上', '某样', '残酷', '每个', '看到', '真正', '秘密', '绝大部分', '美好', '联系', '过去', '这样']
[[0.         0.         0.2236068  0.         0.         0.
  0.4472136  0.         0.         0.         0.         0.
  0.2236068  0.         0.         0.         0.         0.
  0.2236068  0.2236068  0.         0.4472136  0.         0.2236068
  0.         0.4472136  0.2236068  0.         0.         0.
  0.2236068  0.2236068  0.         0.         0.        ]
 [0.         0.         0.         0.2410822  0.         0.
  0.         0.2410822  0.2410822  0.2410822  0.         0.
  0.         0.         0.         0.         0.2410822  0.55004769
  0.         0.         0.         0.         0.2410822  0.
  0.         0.         0.         0.48216441 0.         0.
  0.         0.         0.         0.2410822  0.2410822 ]
 [0.15698297 0.15698297 0.         0.         0.62793188 0.47094891
  0.         0.         0.         0.         0.15698297 0.15698297
  0.         0.15698297 0.15698297 0.15698297 0.         0.1193896
  0.         0.         0.15698297 0.         0.         0.
  0.15698297 0.         0.         0.         0.31396594 0.15698297
  0.         0.         0.15698297 0.         0.        ]]

2.特征预处理

特征预处理就是通过特定的统计方法,将数据转换成算法要求的数据

常使用的方法是归一化与标准化 ,数值型数据的处理方法是归一化、标准化和缺失值处理。
归一化:通过对原始数据进行变换把数据映射到【0,1】之间 ,使得某一个特征不会对结果造成太大的影响。
X’=(x-min)/(max-min) X" = X’*(mx-mi)+mi 其中mx为1,mi为0
但是最大值和最小值容易受异常点的影响,所以这种方法的鲁棒性较差,只适合传统精确小数据的场景。

from sklearn.preprocessing import MinMaxScaler, StandardScaler, Imputer
def mm():
    """
    归一化处理
    :return: NOne
    """
    mm = MinMaxScaler(feature_range=(2, 3))
    data = mm.fit_transform([[90,2,10,40],[60,4,15,45],[75,3,13,46]])
    print(data)
    return None

if __name__ == "__main__":
    mm()

运行结果:

[[3.         2.         2.         2.        ]
 [2.         3.         3.         2.83333333]
 [2.5        2.5        2.6        3.        ]]

标准化:通过对原始数据进行变化,把 数据变换到均值为0,方差为1的范围内。
X’=(x-mean)/标准差,作用于每一列,
标准化总结:在已有样本足够多的情况下比较稳定,适合现代嘈杂大数据场景。

def stand():
    """
    标准化缩放
    :return:
        [[-1.06904497 -1.35873244  0.98058068]
         [-0.26726124  0.33968311  0.39223227]
         [ 1.33630621  1.01904933 -1.37281295]]
        每一列平均值为0,标准差为1
    """
    std = StandardScaler()
    data = std.fit_transform([[90,2,10,40],[60,4,15,45],[75,3,13,46]])
    print(data)
    return None

运行结果:

[[ 1.22474487 -1.22474487 -1.29777137 -1.3970014 ]
 [-1.22474487  1.22474487  1.13554995  0.50800051]
 [ 0.          0.          0.16222142  0.88900089]]

缺失值处理

from sklearn.preprocessing import  Imputer
def im():
    """
    缺失值处理
    :return:NOne
    """
    # NaN, nan,strategy:是填补的策略,axis指行还是列,0是列,1是行
    im = Imputer(missing_values='NaN', strategy='mean', axis=0)
    #缺失的数据必须是np.nan类型,如果不是需要用replase替换一下。
    data = im.fit_transform([[1, 2], [np.nan, 3], [7, 5]])
    print(data)
    return None


运行结果:

[[1. 2.]
 [4. 3.]
 [7. 5.]]

3.数据降维

为什么要进行数据降维:
1.冗余:部分特征的相关度高 2.噪声:部分特征对预测结果有影响。

使用特征选择进行数据将维
特征选择就是提取部分特征作为训练集特征特征在选择前和选择后可以改变值,也可以不改变值。
主要方法:Filter过滤式:variance Threshold, Embedded嵌入式:正则化、决策树Wrapper包裹式

from sklearn.feature_selection import VarianceThreshold
def var():
    """
    特征选择-删除低方差的特征
    :return: None
    """
    #threshold是方差
    var = VarianceThreshold(threshold=1.0)
    data = var.fit_transform([[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]])
    print(data)
    return None

运行结果:

[[0]
 [4]
 [1]]

主成分分析进行特征降维
PCA:将数据分解为较低维数空间。

from sklearn.decomposition import PCA
def pca():
    """
    主成分分析进行特征降维
    :return: None
    """
    #n_components将数据减少到90%,通常是90%~95%
    pca = PCA(n_components=0.9)
    data = pca.fit_transform([[2,8,4,5],[6,3,0,8],[5,4,9,1]])
    print(data)
    return None

if __name__ == "__main__":
    pca()

运行结果:

[[ 1.28620952e-15  3.82970843e+00]
 [ 5.74456265e+00 -1.91485422e+00]
 [-5.74456265e+00 -1.91485422e+00]]


结束语:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值