农产品到餐桌:分类模型的工作流程

原文:towardsdatascience.com/farm-to-table-the-workflow-of-a-classification-model-7abc41989767

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/06aa7371de8e78f1b85ddb72a943751a.png

图片由 ZanUnsplash 提供

简介

典型的机器学习工作流程很少只涉及对当前问题应用单一方法。模型通常经过一个迭代过程,应用并评估各种技术。特征工程策略会被测试、丢弃,然后重新审视;算法及其参数会被穷尽迭代,有时只是为了提高几分之一的百分比。这种实验和精炼的循环过程对于朝着稳健的解决方案努力是至关重要的。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/a7e11518570af8fb359e34ca4a00bab1.png

图片由 MuradiUnsplash 提供

以下文章展示了为给定问题准备、测试、比较和评分分类模型的典型工作流程。在这个例子中,一个假设的烹饪网站的产品团队试图通过实施基于他们手动选择的食谱过去表现的机器学习系统来改进他们当前选择网站首页食谱的系统。为此,应用了两种算法——逻辑回归和随机森林分类器——然后评估并比较了手动方法作为关键性能指标。这个项目的全部细节如下。

食谱推荐系统

问题定义

产品团队要求一个分类模型,能够正确推荐产生高流量的食谱,以取代他们当前的网站选择流程。为此,使用了一个合成数据集(可在该项目 GitHub 文件夹的链接 这里 中找到),包含食谱类别、营养指标(如卡路里、碳水化合物、糖和蛋白质水平)、食谱的份量大小以及目标变量 high_traffic(表示该食谱在网站上产生了高流量)。基于此,他们的要求是生成一个分类模型,能够在网站上至少 80%的时间内推荐热门食谱。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/568545c9a755854083b67b1d68db1dc5.png

图片由Peter DawnUnsplash上提供

首先,可以通过指出产品团队只对模型在预测高流量菜谱方面的能力感兴趣,而对模型在低流量菜谱上的表现几乎没有兴趣来进一步定义问题。因此,这可以理解为对高精度分类模型的请求,并且在此背景下应最大化真正预测。

第 1 步:导入库和数据

首先,我导入了数据分析、操作和可视化的所需库:numpy(np)、pandas(pd)、matplotlib.pyplot(plt)、seaborn(sns)和 missingno(msno)。Missingno 是一个有效的库,用于确定缺失值在整个数据集中的分布,这使得它在数据清理过程中非常有用。

#import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import missingno as msno

我还导入了机器学习预处理、模型实例化和训练以及模型评估的函数。由于模型的精度对产品团队来说很重要,因此精度指标将是产品团队需求中最重要的指标。

#preprocessing
from sklearn.preprocessing import LabelEncoder

#model preparation
from sklearn.model_selection import train_test_split
from sklearn.model_selection import RandomizedSearchCV

#models
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression

#metrics
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score

在此之后,使用 pandas 中的 read_csv()函数从 csv 文件中导入数据。打印数据的头部以确认数据已加载到 pd 数据框 df 中。立即可以清楚地看到营养列(卡路里、碳水化合物、糖、蛋白质)中存在缺失值,需要用适当的值填充。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8593c77d99085e0878e64b94bdee1cb9.png

数据的前五行(作者图片)

第 2 步:数据验证

数据加载到工作区后,下一步是描述数据集并了解其一般形状和信息。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/91114a3e9a18491204f194493074991a.png

数据描述和统计输出(作者图片)

从数据框信息中立即可以观察到一些显著的观察结果;例如,卡路里列具有最高的值范围,最小值为 0.14,最大值为 3705.82。营养列中有 52 个缺失值。调查这些缺失数据的分布将非常重要。此外,高流量列似乎有 373 个缺失值——这也需要被调查。最后,关于份量列的信息表明它是一个对象,而不是浮点数或整数——这表明它可能在某些行中包含字符串数据。这需要在后续模型训练中进行标准化。

为了进一步调查数据集中的值,我定义了一个名为 print_uniques()的自定义函数,用于打印数据框中每一列的所有唯一值及其计数。该函数使用生成器对象遍历每一列,以显示唯一值及其计数。对于每一列,该函数打印列名、唯一值和唯一值的数量。

#function to print all unique values and their counts from each column
def print_uniques(df):
    #for large datasets - using generator for speed
    uniques_generator = ((x, df[x].unique(), df[x].nunique()) for x in df.columns)

    print('nUnique Values:')
    for x, unique_values, num_unique in uniques_generator:
        print(f"{x}: n {unique_values} n ({num_unique} unique values)")

#printing uniques of selected columns
print_uniques(df[['category', 'servings','high_traffic']])

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/a76f428a450aac51bf7f6e5bd8230d8f.png

指定列的唯一值打印输出(图片由作者提供)

从上面的输出中可以看出,份量列有“作为零食 4 份”或“作为零食 6 份”的条目,这些需要被清理。此外,高流量列只有一个唯一值“高”;推测缺失值都是交通流量低的情况,因此这些需要用“低”值填充。

第三部分:数据清理

在完成对数据结构的评估后,msno 现在可以用来可视化缺失数据。高流量列中的缺失值似乎是有结构性的缺失数据,因此使用 fillna()函数(指定任何缺失值为“低”)填充该列中的缺失数据是合理的。对于营养列中的缺失值,首先按卡路里对数据框进行排序,然后使用 msno matrix()函数进行可视化。

#fill missing values in high_traffic column with 'Low'
df['high_traffic'] = df['high_traffic'].fillna('Low')

#sort df by 'calories' column
df_sorted = df.sort_values('calories')

#create matrix of missing values
msno.matrix(df_sorted)
plt.show()

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/b9888da76635b8542110e1911ea46d75.png

完整数据集的 Msno 矩阵(图片由作者提供)

我进一步调查了缺失值是否仅在整个营养列中是常见的。

#using msno to visualise only missing values
msno.bar(df[df.isna().any(axis=1)])
plt.show()

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/5c86c722f711ab3c426b3f80d00f2998.png

缺失营养值的 Msno 矩阵(图片由作者提供)

缺失数据似乎在所有营养列中都是常见的,每当有缺失时;即当卡路里数据缺失时,碳水化合物、糖和蛋白质数据也会缺失。鉴于数据集中的数据点数量很少(947 行),删除这些值(代表超过 5%的数据点)不是一个好的策略。需要应用更智能的策略来处理这些缺失数据。

首先要解决的是初始数据清理任务(更改份量数据类型、获取每份的营养值等),然后适当地填充缺失数据。为此目的的第一个函数是清理份量列。这是通过取份量列的第一个值并将其转换为整数来完成的;从而从一些值中移除了“作为零食”字符串。

def keep_first_character(value):
    return int(str(value)[0])

#apply function to servings column
df['servings'] = df['servings'].apply(keep_first_character)
print(df['servings'].unique()) #print unique values to verify

接下来,定义了一个函数来计算每个营养列(“卡路里”、“蛋白质”、“糖”和“碳水化合物”)的每份服务值。该函数设置了一个新的营养值列,该列是营养值除以服务列。然后将其应用于所有营养列,并捕获在列表中以应用于函数。

#define function to calculate per serving values
def calculate_per_serving(df, columns):
    # looping through columns
    for column in columns:
        df[f'{column}_per_serving'] = df[column] / df['servings']

#defining nutritional columns
nutritional_columns = ['calories', 'protein', 'sugar', 'carbohydrate']

#calculate per serving values
calculate_per_serving(df, nutritional_columns)

在清理了服务数据并创建了每份服务的营养列之后,现在可以对数据集中的缺失数据应用合理的值。

我之前已经确定,只有营养列中的值是缺失的,而其他列(即服务、类别)对于这些行没有缺失数据。因此,可以将每个分类值的平均营养值应用于缺失数据,如下所示(最初我应用了平均值到缺失值,然而通过试验和错误发现,中位数导致了最终模型中更好的指标。)

首先,这是应用于每份服务的营养列,然后通过将每份服务的值乘以每份服务的值来放大总营养列。

#apply median per_serving value to the missing values
for category in df['category'].unique():
    for column in nutritional_columns:
        fill_value = df.loc[df['category'] == category, f'{column}_per_serving'].median()
        print(f"Median {column} for {category}: {(fill_value).round(2)}") #values rounded for display
        df.loc[(df['category'] == category) & (df[f'{column}_per_serving'].isnull()), f'{column}_per_serving'] = fill_value

#multiply per serving column by servings to fill missing values
for column in nutritional_columns:
    df[column] = df[f'{column}_per_serving'] * df['servings']

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/0149a519f3520b30e605dc3bac730223.png

每个类别的中位营养值,用于在缺失数据中填充空值(图片由作者提供)

现在数据已经足够清洁,现在可以对数据进行单变量和多变量分析,以了解其分布。

第四部分:分析与可视化

开始分析时,我调查了不同类别中高流量的分布情况——这是通过为每个类别创建一个计数图并使用 matplotlib 绘制结果来完成的。x 轴标签旋转了 45 度以提高可读性。

#plotting countplots for category
plt.figure(figsize=(10, 6))
sns.countplot(x='category', data=df, order=df['category'].value_counts().index)
plt.title('Category Counts')
plt.xticks(rotation=45)
plt.show()

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1ff8229fd95c8f5de7208d41af05d78b.png

按类别分割的食谱计数图(图片由作者提供)

类别的计数图可以根据高流量和低流量食谱进一步细分,以展示不同类别中流行食谱的变化。

此外,使用交叉表绘制了 Seaborn 热图,用于在每个类别内对高流量和低流量食谱进行注释比较。

#plotting countplots for category vs high_traffic
plt.figure(figsize=(10, 6))
sns.countplot(x='category', hue='high_traffic', data=df, palette=['green', 'red'], order=df['category'].value_counts().index)
plt.title('Category vs High Traffic')
plt.xticks(rotation=45)
plt.show()

#plotting crosstab of category and high_traffic
cat_traffic = pd.crosstab(df['category'], df['high_traffic'])
plt.figure(figsize=(10, 6))
sns.heatmap(cat_traffic, annot=True, cmap='Oranges', cbar=False)
plt.title('Category vs High Traffic')
plt.show()

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/74fafa48b879e0a263280849c3e37feb.png

按类别和 high_traffic 分割的食谱计数图(图片由作者提供)

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/2b7e4cb950d906cbaf0445b2042671c2.png

展示按高流量分类的食谱类别的计数图(图片由作者提供)

在数据集中,饮料类别有最多的食谱,共有 106 道食谱,而鸡胸肉类别最少,有 71 道食谱。早餐类别似乎是最受网站访问者欢迎的,该类别中的大多数食谱都看到了很高的流量。同样,很明显,肉类和土豆类别也非常受欢迎,这些食谱显示了对网站的高流量。相比之下,单菜式食谱类别有最多的低流量食谱,其次是饮料和午餐/小吃。

第 5 步:机器学习预处理

从分类模型的预处理开始,从数据集中删除了每份的列。然后为预处理步骤创建了一个数据框的副本。

#dropping unnecessary columns
drop_cols = ['calories_per_serving', 'protein_per_serving', 'sugar_per_serving', 'carbohydrate_per_serving']
df = df.drop(drop_cols,axis=1)

#creating copy of df for ml
df_ml = df.copy()

在机器学习预处理之前,展示营养列的直方图是有益的,以表明初始数据是如何分布的。

#plotting histograms of nutritional columns
df_ml[nutritional_columns].hist(figsize=(10, 10))

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/378bb268232bd50fd9aa778cea149fc1.png

营养列的直方图(图像由作者提供)

直方图显示营养值都严重右偏斜;对于许多机器学习模型,这种偏斜将需要在模型训练中使用,因此这需要在任何模型训练之前进行标准化。

下一步涉及对营养列应用对数转换。在一个循环中,每个列都使用 NumPy 的 log1p() 函数进行转换,应用自然对数加一来处理零值。需要注意的是,虽然这是一种常见的用于缩放偏斜数据的方 法,但在营养列中没有零值,因此应用简单的对数函数也是可以的。此外,每个转换后的列都使用 rename() 函数重命名,以反映应用到的转换。

#applying log transformation to nutritional columns
for column in nutritional_columns:
    df_ml[column] = np.log1p(df_ml[column])
    #rename column
    df_ml.rename(columns={column: f'log1p_{column}'}, inplace=True)

一旦这种转换完成,再次调用直方图来检查转换后数据的新分布。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/7f60fbd3e3edc5eca6f138fde9daf955.png

转换数据的直方图(图像由作者提供)

卡路里和碳水化合物列似乎从转换中受益匪浅,现在在 log1p 转换下显示出大约正态分布。糖和蛋白质列也显示出一些好处,现在更接近正态分布。在将数值特征应用适当的缩放之前,必须对分类特征进行编码,然后加载到选择的分类模型中。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/37fa38e5268c7e3018271ae41c4988d3.png

Louis HanselUnsplash 拍摄的照片

在对数值列应用转换之后,定义了一个要编码的类别列列表,包含“category”和“servings”。这些列包含需要转换为数值表示以供某些分类算法有效处理的定性信息。重要的是要注意,“high_traffic”列(即目标列)是单独编码的,因为它只有两个不同的值,并且被认为有必要确保“High”值被视为精确度指标的积极目标变量。将“servings”列视为一个类别,因为试验和错误表明,将“servings”作为数据集中的值对某些分类模型指标有积极影响。

在此之后,实例化了一个 LabelEncoder 对象;标签编码是将分类数据转换为数值标签的方法,为列中的每个不同类别分配一个唯一的整数。这种转换允许分类模型解释分类数据。随着代码的循环,将 LabelEncoder 应用于列表中的每个类别列。对于每次迭代,使用 LabelEncoder 的 fit_transform()方法对相应列的分类值进行编码,用它们对应的数值标签替换。

#replace high_traffic column with 1 and 0
df_ml['high_traffic'] = df_ml['high_traffic'].replace({'High': 1, 'Low': 0})

#instantiate LabelEncoder
label_encoder = LabelEncoder()

#list of categorical columns to encode
cat_columns = ['category', 'servings']

#iterate through each column in the list
for column in cat_columns:
    #apply LabelEncoder to encode the column
    df_ml[column] = label_encoder.fit_transform(df_ml[column])

在继续到模型训练步骤之前,将食谱列从数据集中删除。

#drop recipe column
drop_cols = ['recipe']
df_ml = df_ml.drop(drop_cols,axis=1)

第 6 步:模型选择与评估

现在数据已经足够预处理,我接下来将进行构建和训练分类模型。选择了两个模型进行训练,以便相互比较精确度结果,并与随机选择的基线——逻辑回归分类器和随机森林分类器——进行比较。选择逻辑回归是因为它处理小数据集的简便性以及其快速的运行时间。同样,随机森林是一个多功能的算法,不太可能过拟合,这使得它成为此问题的良好替代模型选择。

在数据集上首先测试的模型是一个逻辑回归分类器。模型训练过程从为分类目的创建 dataframe df_ml 的副本开始,命名为 df_model。从 df_model 中提取目标变量,并存储为 y。同样,从 df_model 中移除目标变量,并将得到的 DataFrame 存储在 X 中。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/aad204c51a8914d531c5e7ceb94487a0.png

图片由 Jay WenningtonUnsplash 提供

使用 train_test_split()函数将数据分为训练集和测试集。分割基于 df_model 的‘category’列,测试集大小为 20%,固定随机状态为 42。以这种方式对训练-测试集进行分层,以提供与原始数据集中类别成比例的集合,因为这样做被发现可以略微提升模型指标。实例化一个逻辑回归模型并定义逻辑回归模型的参数网格,包括正则化强度、惩罚、求解器和最大迭代次数等超参数。这样做是为了给交叉验证过程提供更大的机会,以找到模型的最佳超参数。

我随后实例化了一个随机搜索交叉验证(RandomizedSearchCV)来高效地探索超参数空间;随后执行随机搜索以找到最佳超参数,使用 5 折交叉验证最大化精度。在此之后,打印出搜索过程中找到的最佳精度分数和相应的最佳超参数。

#creating copy of the dataframe for classification
df_model = df_ml.copy()

#extract target variable
y = df_model['high_traffic']

#drop target variable from the dataframe
X = df_model.drop(['high_traffic'], axis=1)

#split data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=df_model['category'], test_size=0.2, random_state=42)

#instantiate Logistic Regression model
logistic_regression = LogisticRegression()

#define parameter grid for Logistic Regression
param_grid = {
    'C': [0.001, 0.01, 0.1, 1, 10, 100],
    'penalty': ['l1', 'l2', 'elasticnet', 'none'],
    'solver': ['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga'],
    'max_iter': [100, 200, 300, 400, 500],
    'fit_intercept': [True, False],
    'class_weight': [None, 'balanced'],
    'warm_start': [True, False],
    'multi_class': ['auto', 'ovr', 'multinomial'],
    'random_state': [None, 42]
}

#printing model eval callout
print("Evaluating Logistic Regression:")

#instantiate randomised search CV
random_search_lr = RandomizedSearchCV(logistic_regression, param_distributions=param_grid, n_iter=20, 
                                      scoring='precision', n_jobs=-1, cv=5, random_state=42)

#fit randomised search CV
random_search_lr.fit(X_train, y_train)

#best model
best_model_lr = random_search_lr.best_estimator_

#best precision score
best_precision_lr = random_search_lr.best_score_

#best hyperparameters
best_params_lr = random_search_lr.best_params_

print("nBest Precision:", best_precision_lr)
print("Best Parameters:", best_params_lr)

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4477adf89c9a531c380ca0d181ff1141.png

逻辑回归模型评估(作者图片)

很明显,逻辑回归模型在数据上的表现非常好,使用上述最佳参数的最佳精度为 81.48%,这超过了产品团队要求的 80%的目标精度指标。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/1ba85d8b4245bdb7fefcca0c2856c74c.png

Luisa BrimbleUnsplash上的照片

现在可以将此与替代模型进行比较;随后在数据集上训练随机森林以查看其性能。与之前一样,模型训练过程从创建 dataframe df_ml 的副本并存储为 df_model 开始。从 df_model 中提取目标变量‘high_traffic’并从特征 X 中移除。然后将数据分为训练集和测试集,使用与逻辑回归模型相同的分层方法。

初始化一个随机森林分类器并定义一个参数网格,其中包括估计器的数量、树的最大深度、分割的最小样本数以及叶节点的最小样本数等超参数。然后实例化 RandomizedSearchCV 来遍历参数网格中的超参数。与逻辑回归模型类似,进行随机搜索以找到最佳超参数,使用 5 折交叉验证最大化精度。随后打印出搜索过程中找到的最佳精度分数和相应的最佳超参数。

#creating copy of the dataframe for classification
df_model = df_ml.copy()

#extract target variable
y = df_model['high_traffic']

#drop target variable from the dataframe
X = df_model.drop(['high_traffic'], axis=1)

#split data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=df_model['category'], test_size=0.2, random_state=42)

#instantiate random forest classifier
rf_classifier = RandomForestClassifier()

#define parameter grid for random forest
param_grid = {
    'n_estimators': [50, 100, 200, 300, 400],
    'max_depth': [3, 4, 5, 6, 7],
    'min_samples_split': [2, 3, 4, 5, 6],
    'min_samples_leaf': [1, 2, 3, 4, 5],
    'max_features': ['sqrt', 'log2', None],
    'bootstrap': [True, False],
    'criterion': ['gini', 'entropy']
}

#printing model eval callout
print("Evaluating Random Forest:")

#instantiate randomised search CV
random_search_rf = RandomizedSearchCV(rf_classifier, param_distributions=param_grid, n_iter=20, 
                                      scoring='precision', n_jobs=-1, cv=5, random_state=42)

#fit randomised search CV
random_search_rf.fit(X_train, y_train)

#best model
best_model_rf = random_search_rf.best_estimator_

#best precision score
best_precision_rf = random_search_rf.best_score_

#best hyperparameters
best_params_rf = random_search_rf.best_params_

#printing model metrics
print("nBest Precision:", best_precision_rf)
print("Best Parameters:", best_params_rf)

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/c1f27f7ff48611acf70ea5e4ebf455f1.png

随机森林模型的评估(图片由作者提供)

如上图所示,随机森林模型的表现并不如逻辑回归模型,其最佳精确度值为 78.82%;这略低于产品团队要求的精确度目标值。现在,这两个模型都已经通过随机搜索交叉验证进行了训练和优化,因此可以比较它们的性能与“随机选择”推荐预期的结果。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/4878eed40996913e6d3f5dbe5bac9a1a.png

图片由Sebastian Coman 摄影Unsplash提供

推荐高流量模型的随机选择概率定义为数据集中高流量菜谱的比例——如果随机选择一个菜谱在网站上展示,这将是有可能产生高流量的概率。我将每个模型的精确度指标与随机选择概率进行比较,以便将这些结果置于适当的业务环境中。

#calculating chance of randomly picking high traffic recipe
random_choice = df[df['high_traffic'] == 'High'].count()['high_traffic'] / len(df['high_traffic'])
print(f"Possibility of choosing high traffic recipe at random: {(100*random_choice).round(2)}%")

#displaying final metrics for logistic regression
print("nLogistic Regression - Metrics:")
print(f"Final precision: {(100*best_precision_lr).round(3)}%")
print(f"Percentage improvement over random choice: {(100*(best_precision_lr/random_choice)-100).round(3)}%")

#displaying final metrics for random forest
print("nRandom Forest - Metrics:")
print(f"Final precision: {(100*best_precision_rf).round(3)}%")
print(f"Percentage improvement over random choice: {(100*(best_precision_rf/random_choice)-100).round(3)}%")

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/8dfd7b9645a57fab17aba40e7f813f39.png

逻辑回归和随机森林指标与随机选择方法的比较(图片由作者提供)

如上图所示,与随机选择概率相比,两个模型都有显著提升,逻辑回归模型的表现比随机选择高出 34.4%,随机森林模型的表现比随机选择高出 30.04%。显然,逻辑回归是首选模型,因为它最终精确度达到了 81.48%,符合产品团队的要求。

第 7 步:结论与建议

从分析角度来看,早餐类别似乎是最受网站访问者欢迎的,该类别中的大多数菜谱都看到了高流量。同样,很明显,肉类和土豆类别也非常受欢迎,这些菜谱对网站产生了高流量。因此,如果手动选择网站上的菜谱,这些类别应该是优先考虑的。相比之下,单菜式菜谱类别有最多的低流量菜谱,其次是饮料和午餐/小吃。因此,如果手动选择网站上的菜谱,这些类别应该被降级。

对数据拟合了两个分类模型,一个是随机森林分类器,另一个是逻辑回归分类器。与随机森林模型相比,逻辑回归模型表现更好,最终精确度为 81.48%,而随机森林模型的精确度为 78.82%。逻辑回归模型与随机选择的比较显示,最终模型比随机选择好 34.43%,这表明这是一个比当前商业实践明显更优的方法。同样,随机森林模型也优于随机选择,提高了 30.04%。因此,上述逻辑回归模型是首选模型,因为它满足了产品团队推荐 80%的高流量食谱的要求。因此,这是数据科学团队将推荐给产品团队使用的模型。

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/eec257da43c74a6a4d359d161d6e0026.png

图片由 Sam Moghadam KhamsehUnsplash 提供

在分类模型方面,我建议产品团队收集更多食谱,以便对模型进行更精细的调整。分类模型的最终迭代达到了 81.48%的精确度,这与数据科学团队对产品团队的要求相符。随着更多食谱数据的加入,模型可能被训练以提供比已展示的更高的精确度。在数据分析期间,我注意到饮料类别在数据集中最为常见,然而这个类别也是最受欢迎的之一;因此,产品团队应努力增加数据集中其他类别的食谱数量,以便在训练模型时拥有更多样化的食谱选择。

同样,我建议产品团队在数据集中添加更多关于其他特性的数据,以补充已经提供的数据。例如,估计食谱准备时间、配料数量、食谱难度等特性可能有助于进一步提高模型精度,甚至超过当前模型的精度,从而为网站提供更好的推荐。

最后的想法

总结来说,构建上述烹饪网站食谱选择系统的机器学习模型的过程展示了这类工作流程的复杂性质。从最初的数据预处理到模型选择和评估,这个过程需要创意、分析严谨性以及(尤其是)耐心。构建此类系统的工作高度迭代,在整个训练过程中预期会有许多修订。最终,通过足够的毅力和独创性,这个过程会结出硕果,产生一个设计良好且性能优异的机器学习模型。

需求响应动态冰蓄冷系统与需求响应策略的优化研究(Matlab代码实现)内容概要:本文围绕需求响应动态冰蓄冷系统及其优化策略展开研究,结合Matlab代码实现,探讨了在电力需求侧管理背景下,冰蓄冷系统如何通过优化运行策略参与需求响应,以实现削峰填谷、降低用电成本和提升能源利用效率的目标。研究内容包括系统建模、负荷预测、优化算法设计(如智能优化算法)以及多场景仿真验证,重点分析不同需求响应机制下系统的经济性和运行特性,并通过Matlab编程实现模型求解与结果可视化,为实际工程应用提供理论支持和技术路径。; 适合人群:具备一定电力系统、能源工程或自动化背景的研究生、科研人员及从事综合能源系统优化工作的工程师;熟悉Matlab编程且对需求响应、储能优化等领域感兴趣的技术人员。; 使用场景及目标:①用于高校科研中关于冰蓄冷系统与需求响应协同优化的课题研究;②支撑企业开展楼宇能源管理系统、智慧园区调度平台的设计与仿真;③为政策制定者评估需求响应措施的有效性提供量化分析工具。; 阅读建议:建议读者结合文中Matlab代码逐段理解模型构建与算法实现过程,重点关注目标函数设定、约束条件处理及优化结果分析部分,同时可拓展应用其他智能算法进行对比实验,加深对系统优化机制的理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值