机器学习建模全流程及资料总结——以文本分类风控建模实验为例(1)

场景为根据用户手机短信的风控建模,以此为例总结一套数据处理,特征工程,实验及结果分析的全流程珍贵的代码,并把常用的工具包函数记录清楚,免得每次用都要百度。

如下是一套完整的流程,引自《智能风控》一书,我们按照这样的流程整理博客内容。

 

系列文章包括以下部分:

  1. 数据预处理
  2. 特征工程
  3. 数据存储
  4. 模型实验
  5. 结果分析

 

一. 数据预处理

1. 关于数据读取

原始数据可能以各种格式的文件和各种逻辑关系存储的,常用的读取方式包括:open(file, mode)函数,pandas的pd.read_csv等。

open函数读取时,要注意每一行数据的解析方法,并存储为 list ,dict 等进一步格式。

pandas的工具读取后为DataFrame格式,还需熟悉pandas那一套操作方法。

个人之前两篇关于读文件数据的文章:

python的目录/文件/文本处理概述(入门)

读取多个文件并合并为一个dataframe对象

 

2. 清洗处理

这一部分要进行的工作比较杂,总归来说目的是 形成规整的数据,便于提取特征

因此我们可能需要 清洗脏数据,处理缺失值,处理异常值,如果数据源有多个,还要进行一些数据查询和关联,可以用哈希来关联,数据不多的情况还是建议用DataFrame 对象来处理。

数据量大的情况,可以用df试试看一下内存占用,然后进行优化。

传送门: df对象内存优化,该博客参考的文章是 https://www.kaggle.com/arjanso/reducing-dataframe-memory-size-by-65/notebook  用此方法优化了50%的内存

 

二. 特征工程

总结:sklearn机器学习之特征工程

数据一般有两种形式: 数字和文字。下面我们以短信这个问题为例,介绍文本数据的特征工程。

1. 文本分词

这时必须用到的两款工具 jieba分词和nltk包.

中文分词一般用jieba,网上教程很多,使用方法也很简单。简明 jieba 中文分词教程

最好是对分词的原理和几种分词模式有一定的了解,才能得到适合后面工作的词语。

英文分词原理上就图森破了,下面有两种方法

import nltk.tokenize as tk
tokenizer = tk.WordPunctTokenizer()
tokens = tokenizer.tokenize("Your loan is due 19/02."). # ['Your', 'loan', 'is', 'due', '19', '/', '02', '.']
# 还有切句子的方法 tokenizer.tokenize_sents()

# 这一方法可能切分粗糙一些
from nltk import word_tokenize
tokens = word_tokenize("Your loan is due 19/02.") #['Your', 'loan', 'is', 'due', '19/02', '.']

# 停用词
from nltk.corpus import stopwords
stopwds = stopwords.words("english")

需要注意的是,分词后尤其是英文,需要一些额外的处理,比如转换小写,比如词干还原等,以及停用词/标点符号等去除。

2. 特征提取

2.1 文本的特征提取

分词后每个词的出现都是特征,一元词没有保留语序,因此还可以提取2-gram (N-gram)保留详尽两个词,丰富我们提取到特征的数量,以便后续进一步筛选。这里介绍两个工具。

  • sklearn中 CountVectorizer
  • nltk中BigramCollocationFinder
from sklearn.feature_extraction.text import CountVectorizer
vectorizer = CountVectorizer()                    
CountVectorizer(analyzer=...'word', binary=False, decode_error=...'strict',
 dtype=<... 'numpy.int64'>, encoding=...'utf-8', input=...'content',
 lowercase=True, max_df=1.0, max_features=None, min_df=1,
 ngram_range=(1, 1), preprocessor=None, stop_words=None,
 strip_accents=None, token_pattern=...'(?u)\\b\\w\\w+\\b',
 tokenizer=None, vocabulary=None)

corpus = [
        'This is the first document.',
        'This is the second second document.',
        'And the third one.',
        'Is this the first document?',
        ]
X = vectorizer.fit_transform(corpus)

另外还有 

from sklearn.feature_extraction.text import HashingVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer

参数众多,但是窃以为并不好用。

sklearn中对于文本的特征提取可以参考 https://sklearn.apachecn.org/docs/master/39.html#523-文本特征提取

该工具可以直接将文本向量化,或是one-hot或者tf-idf的特征。对于初学或简单实验的可以直接一用,十分省事。

如果要调整参数,加入一些其他步骤的精细实验,感觉还是可以自己实现每一步,包括建立词表,统计词频,筛选特征,再向量化。在鄙人的代码中,中间进行了一步特征词筛选,因此不方便直接用这个工具进行transform,因此是自己一步步实现的。

import nltk
from nltk.collocations import *
words = ["cat", "run", "dog", "run"]

tflist = nltk.FreqDist(words)

bigram_measures = nltk.collocations.BigramAssocMeasures()
finder = BigramCollocationFinder.from_words(words)

如果是自己一步步提取特征,对于一元词,可以直接用Counter,上述代码里的FreqDist道理一样,统计词及频率,作为后面工作的基础。二元词也可以自己写一个,然后统计词频。

对于文本来说,不用深度学习技术的特征提取,就统计词频即可,然后原文本的序列关系就抛弃掉了。我们只需要保留一个词频的字典即可。

2.2 数值特征提取

对于数值的特征提取,可以进行一些特征的构造,加减乘除,指数对数,对于一些有实际业务意义的特征,可以再根据业务构造有意义的特征。

# 生成多项式特征
preprocessing.PolynomialFeatures()

# 自定义转换器
preprocessing.FunctionTransformer()
transformer = FunctionTransformer(np.log1p, validate=True)

2.3 挖掘特征

简单来说可能是这样的,对于一段文本string1,除了前述分词后的特征,可以制定一个确定的逻辑,相当于一个函数f,f(string) 可以得到one-hot特征,数值特征,布尔类型特征等。

 

3.特征预处理

https://sklearn.apachecn.org/docs/master/40.html#53-预处理数据

这里的预处理,指对模型输入特征值的一些转换,是为了更好的为下游服务。

主要针对一般线性模型的输入值,做一个预处理,内容及相关工具如下:

​# 1. 标准化,去均值和方差按比例缩放
“”“
在机器学习算法的目标函数(例如SVM的RBF内核或线性模型的l1和l2正则化),许多学习算法中目标函数的基础都是假设所有的特征都是零均值并且具有同一阶数上的方差。如果某个特征的方差比其他特征大几个数量级,那么它就会在学习算法中占据主导位置,导致学习器并不能像我们说期望的那样,从其他特征中学习。
”“”
​preprocessing.MinMaxScaler()
preprocessing.MaxAbsScaler()
​preprocessing.StandardScaler(copy=True, with_mean=True, with_std=True)

# 2. 非线性变换
“”“
有两种类型的转换是可用的:分位数转换和幂函数转换。分位数和幂变换都基于特征的单调变换,从而保持了每个特征值的秩。
分位数变换根据公式G-1(F(X))将所有特征置于相同的期望分布中,其中F是特征的累积分布函数,G-1是期望输出值分布G的分位数函数.这个公式基于以下两个事实:
如果X是具有连续累积分布函数F的随机变量,那么F(X)均匀分布在[0,1]
如果U是在[0,1]上的随机分布,那么G-1(U)有分布G.
通过执行秩变换,分位数变换平滑了异常分布,并且比缩放方法受异常值的影响更小。但是它的确使特征间及特征内的关联和距离失真了。
幂变换则是一组参数变换,其目的是将数据从任意分布映射到接近高斯分布的位置。
”“”
# 映射到均匀分布
preprocessing.QuantileTransformer(random_state=0)

# 映射到高斯分布
preprocessing.PowerTransformer(method='box-cox', standardize=False)

# 3. 归一化
preprocessing.normalize(X, norm='l2')

# 4. 类别特征编码
# 序数编码,一般不可用,我们就用下面的独热编码即可
preprocessing.OrdinalEncoder()
# 独热码或dummy encoding
OneHotEncoder(categorical_features=None, categories=None,
       dtype=<... 'numpy.float64'>, handle_unknown='error',
       n_values=None, sparse=True)

# 5. 离散化 (Discretization)
“”“
将连续特征划分为离散特征值的方法。 某些具有连续特征的数据集会受益于离散化,因为 离散化可以把具有连续属性的数据集变换成只有名义属性(nominal attributes)的数据集。 (译者注: nominal attributes 其实就是 categorical features, 可以译为 名称属性,名义属性,符号属性,离散属性 等)
”“”
# 使用k个等宽的bins把特征离散化
preprocessing.KBinsDiscretizer(n_bins=[3, 2, 2], encode='ordinal')
# 将数值特征用阈值过滤得到布尔值
preprocessing.Binarizer(copy=True, threshold=0.0)

这是一些常用的用于特征预处理的工具,用哪个怎么用,需要许多建模经验,结合数据特点和下游模型。。

下一片传送门 机器学习建模全流程及资料总结(2)

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值