关联规则也能有监督?
大家好,我是小伍哥,今天继续跟大家探讨关联规则策略自动化的话题,这次的数据更接近真实场景,这个系列已经写了两篇文章了,第一篇简介基本原理,第二篇讲解策略自动化挖掘,上一篇文章中,我们用关联规则算法进行了风控策略的自动化挖掘,但是需要两步走,先挖掘的策略再进行准确率的评估,稍微有点麻烦,那有没有办法一次性的挖掘就得出策略的准确率呢,把这个算法当然有监督的方法,实际上是可以的,只是相对麻烦点,我们现在开始。
开始前,我们简单的回顾下关联规则的两个概念,这对理解我们的挖掘思路十分重要:
支持度(support):交易记录中某项集出现的概率
项集X的支持度:
项集{X,Y}支持度:
如果支持度太低,说明{X,Y}这条规则在全集中出现的概率小,支持度一般按照项集k值的增加而减少,也就是一元组合的要多于二元组合规则。
置信度(confidence):买了X的人又买了Y,置信度是条件概率P(Y|X)。
1、数据集介绍
我们利用的是一个对直播间弹幕数据集,里面大量涉黄涉暴的文本,挖掘看看哪些是高风险的词汇,可以当成违禁词库,直接进行屏蔽了。该数据集包含19670条明细数据,每一行都用 1(垃圾文本)和 0(正常文本)进行了标记。需要数据集的关注:小伍哥聊风控,回复【弹幕】
正常弹幕示例
新人主播,各位老板多多关注ᚠᚠᚠ 0
50077你卖我 0
看看五雷咒的威力 0
垃圾弹幕示例
网站++沜买的私聊我 1
安 KMD555 买-P-微 1
抠逼加薇2928046748抠逼加薇2928046748抠逼。1
部分数据如下
2、文本读取
import os
import pandas as pd
path = '/Users/wuzhengxiang/Documents/DataSets/TextCnn'
os.chdir(path)
data = pd.read_csv('text_all.csv')
#对数据进行随机打乱
data = data.sample(frac=1, random_state=42)
print(data.shape)
2)
#查看0-1的比例,可以看出来,数据集基本上平衡
data['label'].value_counts()
1 9882
0 9788
#查看前10行的数据
data.head(10)
text label
17036 郑 29526 Q 77544 1
5426 葩葩葩l 0
14173 网站盘需要买的私聊我. 1
14582 买家秀和卖家秀?0
1730 1776看v 0
1444 我又没送你谢我干啥ᚠ 0
10439 7645 55562筘 0
2448 伽韦 sx111505 珂视频箹 Ku 1
10423 影薇 w2753636 1
11782 胸还没有寒磊的 大ᚠ 还奶子疼!0
3、文本预处理
把文本处理成算法需要的格式
# 安装结巴分词 有的话就不用管了
# pip install jieba
#加载结巴分词
import jieba
#使用默认的模式分词即可 测试下分词效果
print(list(jieba.cut('佳喂:sx111505可越qw')))
['佳', '喂', ':', 'sx111505', '可越', 'qw']
#进行分词处理
data['text'] = text_all['text'].apply(lambda x: ' '.join(jieba.cut(x)))
data.head()
#进行替换 并与原来的文本进行合并
'''
label = 1 替换成 Risk
label = 0 替换成 Norm
'''
text_all['label'] = text_all['label'].apply(lambda x: 'Risk' if x>0 else 'Norm')
# 分词处理 并把标签加到序列后面
df_arr = [list(i[0])+([i[1]]) for i in zip(text_all['text'],text_all['label'])]
# 看看处理后前10条数据长啥样
print(df_arr[0:10])
[['颙', ' ', '29526', ' ', 'Q', ' ', '77544', 'Risk'],
['\ufeff', '染', '-', '黄色', ' ', 'K', ' ', 'U', ' ', 'C', ' ', '5', ' ', '3', ' ', '4', 'Risk'],
['91', '网址', '求', '大哥', 'Risk'],
['塞', ' ', 'CC', '-', '名字', '-', '看', '拼', 'ᚰ', 'Risk'],
['QQ', '网名', '!', '微信', 'Norm'],
['佳维', ':', 'sx111505', ' ', '可', '曰', 'Yy', 'Risk'],
['我区', '才', '250', '-', '350w', '买到', 'Norm'],
['君', '-', '伟心', ' ', 'K', 'U', '€', '5', '3', '7', 'Risk'],
['不是', ',', '问', '一些', '愚蠢', '的', '问题', ',', '说', '怎么', '获得', '英雄', ',', '卧槽', '😂', 'Norm'],
['我', '找到', '了', '免费', '网址', 'Risk']]
4、关联规则挖掘
这次我使用FP-growth算法,因为规模比较大,使用的Python包为mlxtend,大家有啥其他好用的可以推荐给我,目前这个用下来还是挺好用的。
# 安装包,如果有 则忽略
pip install mlxtend
#加载包
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori
from mlxtend.frequent_patterns import fpgrowth
from mlxtend.frequent_patterns import association_rules
import pandas as pd
#转换为算法可接受模型(布尔值)
te = TransactionEncoder()
df_tf = te.fit_transform(df_arr)
df = pd.DataFrame(df_tf,columns=te.columns_)
#设置支持度求频繁项集,最小支持度设置为0.005
frequent_itemsets = fpgrowth(df,
min_support=0.005,
use_colnames= True
)
#求关联规则,设置最小置信度为0.3
rules = association_rules(frequent_itemsets,
metric = 'confidence',
min_threshold = 0.3
)
# 查看下输出结果长啥样
rules.columns
['antecedents', 'consequents', 'antecedent support','consequent support', 'support', 'confidence', 'lift', 'leverage','conviction']
# 看前5行数据
rules.head()
antecedents consequents antecedent support ... lift leverage conviction
0 ( ) (Risk) 0.354042 ... 1.559177 0.099459 2.296461
1 (Risk) ( ) 0.502389 ... 1.559177 0.099459 1.441916
2 (Q) (Risk) 0.021352 ... 1.876746 0.009405 8.708185
3 (Q) ( ) 0.021352 ... 2.347047 0.010183 3.821162
4 ( , Q) (Risk) 0.017743 ... 1.910640 0.008117 12.404721
#设置最小提升度
#rules = rules.drop(rules[rules.lift <1.0].index)
#设置标题索引并打印结果
rules.rename(columns = {'antecedents':'from','consequents':'to','support':'sup',
'confidence':'conf'},inplace = True)
rules = rules[['from','to','sup','conf','lift']]
print(rules)
Output from spyder call 'get_namespace_view':
antecedents consequents ... leverage conviction
0 ( ) (Risk) ... 0.099459 2.296461
1 (Risk) ( ) ... 0.099459 1.441916
2 (Q) (Risk) ... 0.009405 8.708185
3 (Q) ( ) ... 0.010183 3.821162
4 ( , Q) (Risk) ... 0.008117 12.404721
... ... ... ... ...
285560 ( , 5176) (157, 4994, Risk) ... 0.005410 54.203533
285561 (5176, Risk) ( , 157, 4994) ... 0.005410 inf
285562 (4994) ( , 157, Risk, 5176) ... 0.005410 54.203533
285563 (157) ( , 5176, 4994, Risk) ... 0.005410 54.203533
285564 (5176) ( , 157, 4994, Risk) ... 0.005410 54.203533
#rules为Dataframe格式,可根据自身需求存入文件 结果为frozenset,转换成dict更好看
rules = rules[rules['to']==frozenset({'Risk'})]
rules['from'] = rules['from'].apply(lambda x:set(x))
rules['to'] = rules['to'].apply(lambda x:set(x))
rules.to_csv('rules.csv',header=True,index=False)
最后的结果如下,其实有很多乱码的字,我们在实际应用的时候,可以做更精细化的特征。
sup:支持度,其实就是这个策略的覆盖程度
conf:置信度,就是这个策略在训练集上的准确率。不用单独计算准确率,非常快捷方便。
5、结 论
这种方法挖掘的策略相对比较少点,但是比较简单,一次性就可以得出准确率。
如果数据需要进一步清洗,可以用下面这个函数试试,数字和字母都会连续的在一起
def TokenClean(s):
'''字符清洗处理'''
lasts = [] #文本序列
is_dn = [] #储存单词
is_en = [] #储存字母
for i in s:
if i.encode('UTF-8').isalnum():#字母
is_en.append(i)
elif not i.encode('UTF-8').isalnum() and len(is_en)>0 :#非字母
is_dn.append(''.join(is_en))
lasts.append(is_dn.pop())
lasts.append(i)
is_en = []
else:
lasts.append(i)
if len(is_en)>0:
is_dn.append(''.join(is_en))
lasts.append(is_dn.pop())
return lasts
TokenClean('然-美-丝-薇 KUC539')
['然', '-', '美', '-', '丝', '-', '薇', ' ', 'KUC539']
df_arr = [TokenClean(i[0])+([i[1]]) for i in zip(text_all['text'],text_all['label'])]
今天就写到这里,要进群的,文末加我的。