机器学习是从数据中自动分析获得规律(模型),并利用规律对未知数据进行预测
让机器学习程序代替手动步骤,减少企业的成本代替企业的效率,如:
工具:
特征工程是将原始数据转换为更好地代表预测模型的潜在问题的特征的过程,从而提高了对未知数据的模型准确性
直接影响预测结果
# sklearn特征抽取API:
sklearn.feature_extraction
对字典数据进行特征值化:
from sklearn.feature_extraction import DictVectorizer
# 实例化
dictVectorizer = DictVectorizer()
# 调用 fit_transform
# 默认返回值:返回sparse矩阵(离散) scipy
data = dictVectorizer.fit_transform(
[{'city': '北京', 'temperature': 100}, {'city': '上海', 'temperature': 60}, {'city': '深圳', 'temperature': 30}])
print(data)
# 特征名称列表
print(dictVectorizer.get_feature_names())
# 返回字典既转换之前数据格式
print(dictVectorizer.inverse_transform(data))
输出:
# 离散解决内存
(0, 1) 1.0
(0, 3) 100.0
(1, 0) 1.0
(1, 3) 60.0
(2, 2) 1.0
(2, 3) 30.0
# DictVectorizer(sparse=False)
# 对应 one-hot 编码
# [[ 0. 1. 0. 100.]
# [ 1. 0. 0. 60.]
# [ 0. 0. 1. 30.]]
['city=上海', 'city=北京', 'city=深圳', 'temperature']
[{'city=北京': 1.0, 'temperature': 100.0}, {'city=上海': 1.0, 'temperature': 60.0}, {'city=深圳': 1.0, 'temperature': 30.0}]
one-hot 编码:为每个类别生成一个布尔列,对于每一个样本,每列只有一个可以为该样本取值 1。
https://hackernoon.com/what-is-one-hot-encoding-why-and-when-do-you-have-to-use-it-e3c6186d008f
╔════════════╦═════════════════╦════════╗
║ CompanyName Categoricalvalue ║ Price ║
╠════════════╬═════════════════╣════════║
║ VW ╬ 1 ║ 20000 ║
║ Acura ╬ 2 ║ 10011 ║
║ Honda ╬ 3 ║ 50000 ║
║ Honda ╬ 3 ║ 10000 ║
╚════════════╩═════════════════╩════════╝
to:
╔════╦══════╦══════╦════════╦
║ VW ║ Acura║ Honda║ Price ║
╠════╬══════╬══════╬════════╬
║ 1 ╬ 0 ╬ 0 ║ 20000 ║
║ 0 ╬ 1 ╬ 0 ║ 10011 ║
║ 0 ╬ 0 ╬ 1 ║ 50000 ║
║ 0 ╬ 0 ╬ 1 ║ 10000 ║
╚════╩══════╩══════╩════════╝
CountVectorizer
每个文档的字/词可以使用其出现次数来进行表示:
使用场景:用于文本分类、情感分析等:
from sklearn.feature_extraction.text import CountVectorizer
# 实例化
cv = CountVectorizer()
# 调用fit_transform方法输入数据并转换,返回sparse矩阵
data = cv.fit_transform(["life is short,i like python","life is too long,i dislike python"])
# 调用get_feature_names()方法,返回单词列表
print(cv.get_feature_names())
# 利用toarray()方法将sparse矩阵转换array数组
print(data.toarray())
输出:
# 词的列表
['dislike', 'is', 'life', 'like', 'long', 'python', 'short', 'too']
# 词频统计
[[0 1 1 1 0 1 1 0]
[1 1 1 0 1 1 0 1]]
https://blog.csdn.net/qq_38890412/article/details/107589938#:~:text=CountVectorizer%E6%98%AF%E9%80%9A%E8%BF%87fit_transform%E5%87%BD%E6%95%B0,%E5%88%B0%E8%AF%8D%E9%A2%91%E7%9F%A9%E9%98%B5%E7%9A%84%E7%BB%93%E6%9E%9C%E3%80%82
https://blog.csdn.net/weixin_38278334/article/details/82320307
需要对中文进行分词才能详细的进行特征值化:
from sklearn.feature_extraction.text import CountVectorizer
import jieba
# 转换成列表
content1 = list(jieba.cut("今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。"))
content2 = list(jieba.cut("我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。"))
content3 = list(jieba.cut(
"如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"))
# 把列表转换成字符串,用空格隔开
c1 = ' '.join(content1)
c2 = ' '.join(content2)
c3 = ' '.join(content3)
print(c1, c2, c3)
# 特征抽取
cv = CountVectorizer()
data = cv.fit_transform([c1, c2, c3])
print(cv.get_feature_names())
print(data.toarray())
输出:
今天 很 残酷 , 明天 更 残酷 , 后天 很 美好 , 但 绝对 大部分 是 死 在 明天 晚上 , 所以 每个 人 不要 放弃 今天 。 我们 看到 的 从 很 远 星系 来 的 光是在 几百万年 之前 发出 的 , 这样 当 我们 看到 宇宙 时 , 我们 是 在 看 它 的 过去 。 如果 只用 一种 方式 了解 某样 事物 , 你 就 不会 真正 了解 它 。 了解 事物 真正 含义 的 秘密 取决于 如何 将 其 与 我们 所 了解 的 事物 相 联系 。
['一种', '不会', '不要', '之前', '了解', '事物', '今天', '光是在', '几百万年', '发出', '取决于', '只用', '后天', '含义', '大部分', '如何', '如果', '宇宙', '我们', '所以', '放弃', '方式', '明天', '星系', '晚上', '某样', '残酷', '每个', '看到', '真正', '秘密', '绝对', '美好', '联系', '过去', '这样']
[[0 0 1 0 0 0 2 0 0 0 0 0 1 0 1 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 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 0 1 1 0 1 0 0 1 0 0 0 1 0 0 0 2 1 0 0 1 0 0]]
TfidfVectorizer
TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
TF-IDF作用:用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。
参考:朴素贝叶斯
from sklearn.feature_extraction.text import TfidfVectorizer
import jieba
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)
print(c1, c2, c3)
tf = TfidfVectorizer()
data = tf.fit_transform([c1, c2, c3])
print(tf.get_feature_names())
print(data.toarray())
输出:
今天 很 残酷 , 明天 更 残酷 , 后天 很 美好 , 但 绝对 大部分 是 死 在 明天 晚上 , 所以 每个 人 不要 放弃 今天 。 我们 看到 的 从 很 远 星系 来 的 光是在 几百万年 之前 发出 的 , 这样 当 我们 看到 宇宙 时 , 我们 是 在 看 它 的 过去 。 如果 只用 一种 方式 了解 某样 事物 , 你 就 不会 真正 了解 它 。 了解 事物 真正 含义 的 秘密 取决于 如何 将 其 与 我们 所 了解 的 事物 相 联系 。
/Users/eddie/PycharmProjects/pythonProject/venv/lib/python3.9/site-packages/sklearn/utils/deprecation.py:87: FutureWarning: Function get_feature_names is deprecated; get_feature_names is deprecated in 1.0 and will be removed in 1.2. Please use get_feature_names_out instead.
warnings.warn(msg, category=FutureWarning)
['一种', '不会', '不要', '之前', '了解', '事物', '今天', '光是在', '几百万年', '发出', '取决于', '只用', '后天', '含义', '大部分', '如何', '如果', '宇宙', '我们', '所以', '放弃', '方式', '明天', '星系', '晚上', '某样', '残酷', '每个', '看到', '真正', '秘密', '绝对', '美好', '联系', '过去', '这样']
# a[i][j] 表示 第 j 个词在第 i 个句子(样本)中重要程度
[[0. 0. 0.21821789 0. 0. 0.
0.43643578 0. 0. 0. 0. 0.
0.21821789 0. 0.21821789 0. 0. 0.
0. 0.21821789 0.21821789 0. 0.43643578 0.
0.21821789 0. 0.43643578 0.21821789 0. 0.
0. 0.21821789 0.21821789 0. 0. 0. ]
[0. 0. 0. 0.2410822 0. 0.
0. 0.2410822 0.2410822 0.2410822 0. 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. 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. ]]
通过特定的统计方法(数学方法)将数据转换成算法要求的数据。
一般将样本+特征按照矩阵来表示,列对应特征,行对应样本
特点:通过对原始数据进行变换把数据映射到(默认为[0,1])之间
使得某一特征对最终结果不会造成更大影响,需要进行归一化
x ′ = x − m i n m a x − m i n x ′ ′ = x ′ ∗ ( m x − m i ) + m i x' = \frac{x - min}{max - min} \\ x'' = x' * (m_x - m_i) + m_i x′=max−minx−minx′′=x′∗(mx−mi)+mi
其中 m a x max max m i n min min 为列最大最小, m x m_x mx m i m_i mi 为指定区间一般取 m x = 1 m_x = 1 mx=1 m i = 0 m_i = 0 mi=0, x x x 是原始数据, x ′ ′ x'' x′′ 是最终结果,
from sklearn.preprocessing import MinMaxScaler
# 修改feature_range参数来控制缩放范围,默认(0,1)
mm = MinMaxScaler(feature_range=(2, 3))
data = mm.fit_transform([{90, 2, 10, 40}, [60, 4, 15, 45], [75, 3, 13, 46]])
print(data)
[[3. 2. 2. 2. ]
[2. 3. 3. 2.83333333]
[2.5 2.5 2.6 3. ]]
如果数据中异常点较多,会有什么影响?
通过对原始数据进行变换把数据变换到均值为0, 方差为1 范围内
使得某一特征对最终结果不会造成更大影响,需要进行归一化
x ′ = x − m e a n σ x' = \frac{x - mean}{\sigma} x′=σx−mean
其中, σ \sigma σ 是标准差
对比:
from sklearn.preprocessing import StandardScaler
# 处理之后每列来说所有数据都聚集在均值0附近方差为1
std = StandardScaler()
data = std.fit_transform([[1., -1., 3.], [2., 4., 2.], [4., 6., -1.]])
print(data)
总结:
标准化在已有样本足够多的情况下比较稳定,适合现代嘈杂大数据场景。
from sklearn.impute import SimpleImputer
import numpy as np
# NaN, nan
im = SimpleImputer(missing_values=np.nan, strategy='mean')
data = im.fit_transform([[1, 2], [np.nan, 3], [7, 6]])
print(data)
https://scikit-learn.org/stable/modules/impute.html