赞
踩
目录
数据源自最简数据挖掘系列,Email英文的邮件内容,其中Label列ham为正常邮件、spam为垃圾邮件。数据获取见文末
统计邮件是否为垃圾邮件的标签分布如下,可以看到4458样本中有592条垃圾邮件
处理简写、小写化、去除停用词、词性还原
- from nltk.stem import WordNetLemmatizer
- from nltk.corpus import stopwords
- from nltk.tokenize import sent_tokenize
- import nltk
-
- def replace_abbreviation(text):
-
- rep_list=[
- ("it's", "it is"),
- ("i'm", "i am"),
- ("he's", "he is"),
- ("she's", "she is"),
- ("we're", "we are"),
- ("they're", "they are"),
- ("you're", "you are"),
- ("that's", "that is"),
- ("this's", "this is"),
- ("can't", "can not"),
- ("don't", "do not"),
- ("doesn't", "does not"),
- ("we've", "we have"),
- ("i've", " i have"),
- ("isn't", "is not"),
- ("won't", "will not"),
- ("hasn't", "has not"),
- ("wasn't", "was not"),
- ("weren't", "were not"),
- ("let's", "let us"),
- ("didn't", "did not"),
- ("hadn't", "had not"),
- ("waht's", "what is"),
- ("couldn't", "could not"),
- ("you'll", "you will"),
- ("i'll", "i will"),
- ("you've", "you have")
- ]
- result = text.lower()
- for word_replace in rep_list:
- result=result.replace(word_replace[0],word_replace[1])
-
- return result
-
- def drop_char(text):
- result=text.lower()
- result=re.sub('[^\w\s]',' ',result) # 去掉标点符号、特殊字符
- result=re.sub('\s+',' ',result) # 多空格处理为单空格
- return result
-
- def stemed_words(text,stop_words,lemma):
-
- word_list = [lemma.lemmatize(word, pos='v') for word in text.split() if word not in stop_words]
- result=" ".join(word_list)
- return result
-
- def text_preprocess(text):
-
- if pd.isnull(text):
- return None
-
- stop_words = stopwords.words("english")
- lemma = WordNetLemmatizer()
-
- result=replace_abbreviation(text)
- result=drop_char(result)
- result=stemed_words(result,stop_words,lemma)
- return result
-
- test_index=list(df.sample(int(df.shape[0]*0.7)).index)
- df['label']=np.where(df.index.isin(test_index),'test','train')
- df['label'].value_counts()
- def tf_init_params():
- params_count={
- 'analyzer': 'word', # 取值'word'-分词结果为词级、'char'-字符级(结果会出现he is,空格在中间的情况)、'char_wb'-字符级(以单词为边界),默认值为'word'
- 'binary': False, # boolean类型,设置为True,则所有非零计数都设置为1.(即,tf的值只有0和1,表示出现和不出现)
- 'decode_error': 'strict',
- 'dtype': np.float64, # 输出矩阵的数值类型
- 'encoding': 'utf-8',
- 'input': 'content', # 取值filename,文本内容所在的文件名;file,序列项必须有一个'read'方法,被调用来获取内存中的字节;content,直接输入文本字符串
- 'lowercase': True, # boolean类型,计算之前是否将所有字符转换为小写。
- 'max_df': 1.0, # 词汇表中忽略文档频率高于该值的词;取值在[0,1]之间的小数时表示文档频率的阈值,取值为整数时(>1)表示文档频数的阈值;如果设置了vocabulary,则忽略此参数。
- 'min_df': 1, # 词汇表中忽略文档频率低于该值的词;取值在[0,1]之间的小数时表示文档频率的阈值,取值为整数时(>1)表示文档频数的阈值;如果设置了vocabulary,则忽略此参数。
- 'max_features': 50, # int或 None(默认值).设置int值时建立一个词汇表,仅用词频排序的前max_features个词创建语料库;如果设置了vocabulary,则忽略此参数。
- 'ngram_range': (1, 2), # 要提取的n-grams中n值范围的下限和上限,min_n <= n <= max_n。
- 'preprocessor': None, # 覆盖预处理(字符串转换)阶段,同时保留标记化和 n-gram 生成步骤。仅适用于analyzer不可调用的情况。
- 'stop_words': 'english', # 仅适用于analyzer='word'。取值english,使用内置的英语停用词表;list,自行设置停停用词列表;默认值None,不会处理停用词
- 'strip_accents': None,
- 'token_pattern': '(?u)\\b\\w\\w+\\b', # 分词方式、正则表达式,默认筛选长度>=2的字母和数字混合字符(标点符号被当作分隔符)。仅在analyzer='word'时使用。
- 'tokenizer': None, # 覆盖字符串标记化步骤,同时保留预处理和 n-gram 生成步骤。仅适用于analyzer='word'
- 'vocabulary': None, # 自行设置词汇表(可设置字典),如果没有给出,则从输入文件/文本中确定词汇表
- }
- return params_count
-
- def CountVectorizer_train(train_data,params):
- cv = CountVectorizer(**params)
- # 输入训练集矩阵,每行表示一个文本
-
- # 训练,构建词汇表以及词项idf值,并将输入文本列表转成VSM矩阵形式
- cv_fit = cv.fit_transform(train_data)
- return cv
-
-
- train_data = ["Chinese Beijing Chinese",
- "Chinese Chinese Shanghai",
- "Chinese Macao",
- "Tokyo Japan Chinese"]
-
- params=tf_init_params()
- cv_model=CountVectorizer_train(df[df.label=='train'].clean_text,params)
- df_tf=pd.DataFrame(cv_model.transform(df.clean_text).toarray(),columns=cv_model.get_feature_names_out()).add_prefix('tf_')
- df_tf
- def tfidf_init_params():
- params={
- 'analyzer': 'word', # 取值'word'-分词结果为词级、'char'-字符级(结果会出现he is,空格在中间的情况)、'char_wb'-字符级(以单词为边界),默认值为'word'
- 'binary': False, # boolean类型,设置为True,则所有非零计数都设置为1.(即,tf的值只有0和1,表示出现和不出现)
- 'decode_error': 'strict',
- 'dtype': np.float64, # 输出矩阵的数值类型
- 'encoding': 'utf-8',
- 'input': 'content', # 取值filename,文本内容所在的文件名;file,序列项必须有一个'read'方法,被调用来获取内存中的字节;content,直接输入文本字符串
- 'lowercase': True, # boolean类型,计算之前是否将所有字符转换为小写。
- 'max_df': 1.0, # 词汇表中忽略文档频率高于该值的词;取值在[0,1]之间的小数时表示文档频率的阈值,取值为整数时(>1)表示文档频数的阈值;如果设置了vocabulary,则忽略此参数。
- 'min_df': 1, # 词汇表中忽略文档频率低于该值的词;取值在[0,1]之间的小数时表示文档频率的阈值,取值为整数时(>1)表示文档频数的阈值;如果设置了vocabulary,则忽略此参数。
- 'max_features': 50, # int或 None(默认值).设置int值时建立一个词汇表,仅用词频排序的前max_features个词创建语料库;如果设置了vocabulary,则忽略此参数。
- 'ngram_range': (1, 1), # 要提取的n-grams中n值范围的下限和上限,min_n <= n <= max_n。
- 'norm': None, # 输出结果是否标准化/归一化。l2:向量元素的平方和为1,当应用l2范数时,两个向量之间的余弦相似度是它们的点积;l1:向量元素的绝对值之和为1
- 'preprocessor': None, # 覆盖预处理(字符串转换)阶段,同时保留标记化和 n-gram 生成步骤。仅适用于analyzer不可调用的情况。
- 'smooth_idf': True, # 在文档频率上加1来平滑 idf ,避免分母为0
- 'stop_words': 'english', # 仅适用于analyzer='word'。取值english,使用内置的英语停用词表;list,自行设置停停用词列表;默认值None,不会处理停用词
- 'strip_accents': None,
- 'sublinear_tf': False, # 应用次线性 tf 缩放,即将 tf 替换为 1 + log(tf)
- 'token_pattern': '(?u)\\b\\w\\w+\\b', # 分词方式、正则表达式,默认筛选长度>=2的字母和数字混合字符(标点符号被当作分隔符)。仅在analyzer='word'时使用。
- 'tokenizer': None, # 覆盖字符串标记化步骤,同时保留预处理和 n-gram 生成步骤。仅适用于analyzer='word'
- 'use_idf': True, # 是否计算idf,布尔值,False时idf=1。
- 'vocabulary': None, # 自行设置词汇表(可设置字典),如果没有给出,则从输入文件/文本中确定词汇表
- }
- return params
-
- def TfidfVectorizer_train(train_data,params):
- tv = TfidfVectorizer(**params)
- # 输入训练集矩阵,每行表示一个文本
-
- # 训练,构建词汇表以及词项idf值,并将输入文本列表转成VSM矩阵形式
- tv_fit = tv.fit_transform(train_data)
- return tv
-
- tfidf_model=TfidfVectorizer_train(df[df.label=='train'].clean_text,tfidf_init_params())
- df_tfidf=pd.DataFrame(tfidf_model.transform(df.clean_text).toarray(),columns=tfidf_model.get_feature_names_out()).add_prefix('tfidf_')
- df_tfidf
分别使用tf特征、tfidf特征、tf+tfidf特征构建二分类模型,对比评估模型效果如下
- def init_params():
- params_lgb={
- 'boosting_type': 'gbdt',
- 'objective': 'binary',
- 'metric':'auc',
- 'n_jobs': 8,
- 'n_estimators':300,
- 'learning_rate': 0.01,
- 'max_depth':3,
- 'num_leaves': 8,
- 'max_bin':255,
- 'subsample_for_bin':100000,
- 'min_split_gain':0,
- 'min_child_samples':1,
- 'colsample_bytree': 0.8,
- 'subsample': 0.8,
- 'subsample_freq': 1,
- 'feature_fraction_seed':2,
- 'bagging_seed': 1,
- 'reg_alpha':1,
- 'reg_lambda':1,
- 'scale_pos_weight':1,
- 'silent':True,
- 'random_state':1,
- 'verbose':-1, # 控制模型训练过程的输出信息,-1为不输出信息
- }
- return params_lgb
-
- def ks_auc_value(y_true,df,model):
- y_pred=model.predict_proba(df)[:,1]
- fpr,tpr,thresholds= roc_curve(list(y_true),list(y_pred))
- ks=max(tpr-fpr)
- auc= roc_auc_score(list(y_true),list(y_pred))
- return ks,auc
-
- def model_train_sklearn(train,y_name,fea_list):
-
- params=init_params()
- x_train,x_test =df[df.label=='train'][fea_list],df[df.label=='test'][fea_list]
- y_train,y_test =df[df.label=='train'][y_name],df[df.label=='test'][y_name]
-
- model=lgb.LGBMClassifier(**params)
-
- model.fit(x_train,y_train,eval_set=[(x_train, y_train),(x_test, y_test)])
- train_ks,train_auc=ks_auc_value(y_train,x_train,model)
- test_ks,test_auc=ks_auc_value(y_test,x_test,model)
-
- dic={
- 'train_good':(y_train.count()-y_train.sum()),
- 'train_bad':y_train.sum(),
- 'test_good':(y_test.count()-y_test.sum()),
- 'test_bad':y_test.sum(),
- 'train_ks':train_ks,
- 'train_auc':train_auc,
- 'test_ks':test_ks,
- 'test_auc':test_auc,
- }
- return dic,model
关注威信公众号 Python风控模型与数据分析,回复 垃圾邮件分类 获取本篇数据及代码
还有更多理论、代码分享等你来拿
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。