2.Kaggle:根据所放调料预测菜品属于哪一个菜系(LogisticRegression)

Kaggle:根据所放调料预测菜品属于哪一个菜系**

实验任务:给定佐料名称,预测菜品所属的菜系。
实验步骤
1. 菜品数据载入;
2. 佐料名称预处理,并预览数据集结构;
3. 载入逻辑回归模型,并训练;
4. 结果测试并提交,查看实验分数。

具体描述:

  1. List_one

本文采用sklearn中的逻辑回归模型:LogisticRegression,从sklearn.model_selection导入GridSearchCV, 参数自动搜索,模型得分为0.78

  1. List_two
    对该模型进行改进,采用得到

第一步.下载并导入数据

1. 数据集下载

项目来自Kaggle四年前的一个竞赛项目,项目链接:What`s Cooking?
可以在该处下载所需要的数据集
竞赛数据集
数据集组成:test.json,train.json,sample_submission.csv
train.json:训练所需要的数据集
test.json:测试所需要的数据集,在通过建立模型,用训练数据集训练好模型后,利用测试数据集生成如sample_submission.csv相似的文件,即可在Kaggle上进行提交。

`

2. 数据集导入

数据集后缀名为json,可以使用Pandas导入:(使用Pandas.read_json)

train_filename='train.json'
train_content = pd.read_json(codecs.open(train_filename, mode='r', encoding='utf-8'))

test_filename = 'test.json'
test_content = pd.read_json(codecs.open(test_filename, mode='r', encoding='utf-8'))

.

3. 数据集介绍

该数据集一共包含39774个训练数据,9944个测试数据

训练之前需要了解数据集的组成:

print(train_content.head(5))

在这里插入图片描述
数据集第一列为序号ID,第二列为cuisine(分类菜系),第三例为ingredients()
整个数据集的总的菜系数为20

categories=np.unique(train_content['cuisine'])
print("一共包含 {} 种菜品,分别是:\n{}".format(len(categories),categories))
		一共包含 20 种菜品,分别是:
		['brazilian' 'british' 'cajun_creole' 'chinese' 'filipino' 'french' 'greek'
		 'indian' 'irish' 'italian' 'jamaican' 'japanese' 'korean' 'mexican'
		 'moroccan' 'russian' 'southern_us' 'spanish' 'thai' 'vietnamese']

.

第二步.分析数据

该竞赛的目的是建立一个分类器,通过所使用的调料来推测其菜系属性,需要将数据集分为FeaturesTarget Variables
Feature:是分类的原因,在此数据集为:“ingredients”
Target Variables:是分类的目标,在此数据集为:"cuisine"

.

1. 数据提取

将训练数据集的Feature提取到train_integredients变量中
将·Target Variables提取到train_targets变量中

### TODO:将特征与目标变量分别赋值
train_ingredients = train_content['ingredients']
train_targets = train_content['cuisine']

### TODO: 打印结果,检查是否正确赋值
print(train_ingredients)
print(train_targets)

.

2. 特征分析

第三步.建立模型

1. 数据过滤

由于菜品所包含的佐料很多,同一种佐料也可能有单复数、时态等变化,需要对integredients进行过滤

import re
from nltk.stem import WordNetLemmatizer
import numpy as np

def text_clean(ingredients):
    #去除单词的标点符号,只保留 a..z A...Z的单词字符
    ingredients= np.array(ingredients).tolist()
    print("菜品佐料:\n{}".format(ingredients[9]))
    ingredients=[[re.sub('[^A-Za-z]', ' ', word) for word in component]for component in ingredients]
    print("去除标点符号之后的结果:\n{}".format(ingredients[9]))

    # 去除单词的单复数,时态,只保留单词的词干
    lemma=WordNetLemmatizer()
    ingredients=[" ".join([ " ".join([lemma.lemmatize(w) for w in words.split(" ")]) for words in component])  for component in ingredients]
    print("去除时态和单复数之后的结果:\n{}".format(ingredients[9]))
    return ingredients

print("\n处理训练集...")
train_ingredients = text_clean(train_content['ingredients'])
print("\n处理测试集...")
test_ingredients = text_clean(test_content['ingredients'])

由于使用的数据集对佐料的描述都是文本,需要将文本全部转化为向量,才能进行训练。
使用的方法是IF-IDF
IF-IDF(term frequency-inverse document frequency):词频-逆向文件频率。在处理文本时,如何将文字转化为模型可以处理的向量呢?IF-IDF就是这个问题的解决方案之一。字词的重要性与其在文本中出现的频率成正比(IF),与其在语料库中出现的频率成反比(IDF)。

IF:词频。IF(w)=(词w在文档中出现的次数)/(文档的总词数)

IDF:逆向文件频率。有些词可能在文本中频繁出现,但并不重要,也即信息量小,如is,of,that这些单词,这些单词在语料库中出现的频率也非常大,我们就可以利用这点,降低其权重。IDF(w)=log_e(语料库的总文档数)/(语料库中词w出现的文档数)

IF-IDF:将上面的IF-IDF相乘就得到了综合参数:IF-IDF=IF*IDF

实现的代码如下:

from sklearn.feature_extraction.text import TfidfVectorizer
# 将佐料转换成特征向量

# 处理 训练集
vectorizer = TfidfVectorizer(stop_words='english', ngram_range=(1, 1),
                analyzer='word', max_df=.57, binary=False,
                token_pattern=r"\w+",sublinear_tf=False)
train_tfidf = vectorizer.fit_transform(train_ingredients).todense()

## 处理 测试集
test_tfidf = vectorizer.transform(test_ingredients)

对处理后的数据进行验证:

print(train_tfidf[0:4])

[[ 0. 0. 0. …, 0. 0. 0.]
[ 0. 0. 0. …, 0. 0. 0.]
[ 0. 0. 0. …, 0. 0. 0.]
[ 0. 0. 0. …, 0. 0. 0.]]

2. 创建验证集

运用 sklearn.model_selection 中 train_test_split。
设置test_size为0.2,划分出20%的验证集,80%的数据留作新的训练集。
设置random_state随机种子,以确保每一次运行都可以得到相同划分的结果。(随机种子固定,生成的随机序列就是确定的)

from sklearn.model_selection import train_test_split

X_train , X_valid , y_train, y_valid = 
train_test_split(train_tfidf,train_targets,test_size=0.2,random_state=1)

3. 建立模型和训练

使用sklearn中的逻辑回归模型:Logistic Regression
sklearn.model_selection导入GridSearchCV, 参数自动搜索,只要把参数输进去,就能给出最优的结果和参数,这个方法适合小数据集。

LogisticRegression:

【penalty参数】
类型:str,‘l1’ or ‘l2’,default:‘l2’
选择正则化参数,str类型,可选L1和L2正则化,默认是L2正则化
通过正则化解决过拟合问题
L2指权重衰减
【tol参数】
float, default: 1e-4
对停止标准的容忍,即求解到多少的时候认为已经求得最优解,并停止。float类型,默认值为1e-4
【C参数】
float, default: 1.0
设置正则化强度的逆,值越小,正则化越强。float类型,默认值为1.0。
GridSearchCV:自动调参
相当于写一堆循环,自己设定参数列表,一个一个试,找到最合适的参数
parameters = {‘C’:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
代表调整的是LogisticRegression中的C参数,值为:1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
C是正则化系数的倒数,C越大正则化强度越小。

parameters = {'C':[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
classifier = LogisticRegression()
grid = GridSearchCV(classifier, parameters)

grid = grid.fit(X_train, y_train)

分类结果可视化

4. 模型验证

利用制作的验证集验证训练好的模型的预测结果并计算精度
from sklearn.metrics import accuracy_score ## 计算模型的准确率

from sklearn.metrics import accuracy_score ## 计算模型的准确率

valid_predict = grid.predict(X_valid)
valid_score = accuracy_score(y_valid,valid_predict)

print("验证集上的得分为:{}".format(valid_score))

5. 模型验证结果

.
结果可视化

第四步.模型测试

1. 预测测试集

predictions = grid.predict(test_tfidf)
print("预测的测试集个数为:{}".format(len(predictions)))
test_content['cuisine'] = predictions
test_content.head(10)

2. 结果提交

在第一步提到了Kaggle竞赛需要提交的CSV文件,需要对测试集的预测结果保存为csv文件。

submit_frame = pd.read_csv("sample_submission.csv")
## 保存结果
result = pd.merge(submit_frame, test_content, on="id", how='left')
result = result.rename(index=str, columns={"cuisine_y": "cuisine"})
test_result_name = "tfidf_cuisine_test.csv"
result[['id','cuisine']].to_csv(test_result_name,index=False)

全部代码

在这里插入代码片

猜你喜欢

转载自blog.csdn.net/qq_24074049/article/details/101038174