使用 ChatGPT 进行数据科学项目的指南

推荐指数

本文最后由 Demo Marco 更新于 2025-02-22. 如有资源已失效,请留言反馈,将会及时处理。 【推荐:不翻墙访问被墙网站方法 | 自用高速专线机场 | 高速CN2线路 | 高质量家宽住宅IP

我们都知道 ChatGPT 的流行程度以及人们如何使用它来提高工作效率。但是,如果您是新手,则值得注册 ChatGPT 免费试用版并试用它的所有功能。

使用 ChatGPT 进行端到端数据科学项目

在该项目中,我们将使用来自 DataLab 的贷款数据并围绕它规划数据科学项目。 

ChatGPT 在这里完成了 80% 的工作,我们只需掌握提示工程就可以让一切正确,为此,我们有了令人惊叹的ChatGPT 数据科学备忘单。它附带了 60 多个基于 SQL、R 和 Python 的数据科学任务的 ChatGPT 提示。 

项目规划

这是项目中最重要的部分,我们会根据可用的资源和目标来制定最佳策略。 

您可以访问chat.openai.com并发起新的聊天。之后,我们将提及可用的贷款数据集,并要求 ChatGPT 提出构建端到端通用投资组合项目的步骤。 

提示“我有一个由 9500 行和 14 列组成的贷款数据集:[‘credit.policy'、'purpose'、'int.rate'、'installment'、'log.annual.inc'、'dti'、'fico'、'days.with.cr.line'、'revol.bal'、'revol.util'、'inq.last.6mths'、'delinq.2yrs'、'pub.rec'、'not.fully.paid']。您能列出我必须遵循的步骤来为我的投资组合开发一个端到端项目吗?”

我们确实拿到了名单,但是忘了提及类别不平衡问题,以及项目目标,那就是准确预测“贷款未偿还”。 

更新提示“请包括类别不平衡问题,并准确预测贷款是否不会偿还,而不是贷款是否会偿还。”

再说一遍,我们对模型监控不感兴趣,我们想构建一个 Gradio 应用程序并将其部署在 Huggingface Spaces 上。 

更新提示“我们将使用 Gradio 创建一个 Web 应用程序并将其部署在 Spaces 上,并且我们不会在生产中监控该模型。”

作者的 Gif | 项目所涉及步骤的最终列表

我们得到了如上所示的 9 个步骤的列表,以及如何执行每个步骤的详细说明。 

以下是我们将在本教程中遵循的任务列表:

  • 数据清理和预处理。处理缺失值、将分类变量转换为数字变量、缩放/规范化数据以及处理数据中的任何离群值或异常。此外,您还需要通过对少数类(未全额支付的贷款)进行过度采样或对多数类(全额支付的贷款)进行欠采样来解决类别不平衡问题。
  • 探索性数据分析 (EDA)。探索数据集以深入了解数据,例如变量的分布、变量之间的相关性以及识别数据中的任何模式。
  • 特征工程。创建新特征或转换现有特征以提高模型的预测能力。 
  • 模型选择。尝试几种模型,例如决策树、随机森林、逻辑回归或支持向量机 (SVM)。 
  • 模型训练和评估。在数据上训练选定的模型,并使用准确度、精确度、召回率和 F1 分数等各种指标评估其性能。 
  • 超参数调整。对所选模型的超参数进行微调以提高其性能。 
  • 使用 Gradio 创建 Web 应用程序。一旦您选择了最佳模型,您就可以使用 Gradio 创建 Web 应用程序。 
  • 在 Spaces 上部署 Web 应用程序。使用 Gradio 创建 Web 应用程序后,您可以将其部署在 Spaces 上。 
  • 测试 Web 应用程序。测试它以确保它按预期运行。

探索性数据分析 (EDA) 

探索性数据分析主要涉及数据处理、统计分析和数据可视化。我们可以通过编写后续提示来完成它,该提示是关于编写用于数据集探索性数据分析的 Python 代码。 

后续提示“请编写 Python 代码来加载贷款数据集并执行探索性数据分析 (EDA)”

机器人将理解上下文,并给出带有注释的 Python 代码以及其工作原理的详细解释。 

作者的 Gif | EDA 的 Python 代码

  1. 将数据集加载并显示为 Pandas 数据框。 
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

loan_df = pd.read_csv("loan_data.csv")

loan_df.head()


此代码导入了数据分析和可视化所需的库,即 pandas、matplotlib 和 seaborn。然后,它使用pd.read_csv()函数读取名为“loan_data.csv”的 CSV 文件并将其分配给名为 的变量loan_df。最后,它使用函数显示数据集的前五行head()。这使用户可以快速检查数据并了解其结构和内容。
  1. 显示数值变量的行数和列数以及统计摘要。 
# Display the number of rows and columns in the dataset
print("Number of rows and columns:", loan_df.shape)

# Display summary statistics for numerical variables
print(loan_df.describe())
该代码是用 Python 编写的,用于显示有关名为的数据集的信息loan_df。


第一行代码使用数据框shape的属性loan_df显示数据集中的行数和列数。输出将是一个包含两个值的元组,第一个值表示行数,第二个值表示列数。


第二行代码使用数据框describe()的方法loan_df显示数据集中数值变量的汇总统计数据。这将包括数据集中每个数值列的计数、平均值、标准差、最小值和最大值。


这两行代码对于快速概览数据集并了解其基本特征很有用。

Number of rows and columns: (9578, 14)
credit.policy int.rate ... pub.rec not.fully.paid
count 9578.000000 9578.000000 ... 9578.000000 9578.000000
mean 0.804970 0.122640 ... 0.062122 0.160054
std 0.396245 0.026847 ... 0.262126 0.366676
min 0.000000 0.060000 ... 0.000000 0.000000
25% 1.000000 0.103900 ... 0.000000 0.000000
50% 1.000000 0.122100 ... 0.000000 0.000000
75% 1.000000 0.140700 ... 0.000000 0.000000
max 1.000000 0.216400 ... 5.000000 1.000000

此代码片段显示数据集的描述性统计数据摘要。第一行显示数据集中的行数和列数。其余行显示数据集中每列的计数、平均值、标准差、最小值、最大值和四分位数。


数据集中的列标记为“credit.policy”、“int.rate”、“installment”、“log.annual.inc”、“dti”、“fico”、“days.with.cr.line”、“revol.bal”、“revol.util”、“inq.last.6mths”、“delinq.2yrs”、“pub.rec”和“not.fully.paid”。


统计数据是使用 Python 中的 Pandas 库计算的,它提供了一种分析和处理数据的便捷方法。“count”统计数据显示每列中非缺失值的数量,而“mean”统计数据显示平均值。“std”统计数据显示标准差,用于测量值的分散程度。“min”和“max”统计数据分别显示每列中的最小值和最大值。四分位数显示将数据分成四个相等部分的值。
  1. 显示每列中的缺失值。如我们所见,没有缺失值。 
print(loan_df.isnull().sum())
此代码使用 Python 编程语言打印loan_df数据框每列中的空值总和。


首先,在数据框isnull()上调用该方法loan_df,返回一个布尔数据框,其中True表示空值,False表示非空值。


然后,sum()在此布尔数据框上调用该方法,对True每列中的值的数量进行求和。


最后,使用该函数将每列的结果总和打印到控制台print()。
credit.policy        0
purpose 0
int.rate 0
installment 0
log.annual.inc 0
dti 0
fico 0
days.with.cr.line 0
revol.bal 0
revol.util 0
inq.last.6mths 0
delinq.2yrs 0
pub.rec 0
not.fully.paid 0

此代码片段实际上不是可执行代码,而是 Python 中表格或数据框的表示。每行代表数据集中的一个特征或变量,行右侧的数字代表该特征的缺失值数量。代码只是显示数据集中每个特征的缺失值数量。
  1. 可视化目标变量“not.fully.paid”的分布
sns.countplot(x="not.fully.paid", data=loan_df)
plt.show()

此代码使用 Python 库 Seaborn 创建 loan_df 数据框中“not.fully.paid”列的计数图。计数图显示列中每个唯一值的出现次数。x 参数指定用于 x 轴的列,data 参数指定要使用的数据框。plt.show() 函数用于显示该图。

  1. 可视化变量之间的相关性。
corr = loan_df.corr()
sns.heatmap(corr, annot=True, cmap="coolwarm")
plt.show()

此代码生成名为 的 DataFrame 的相关矩阵的热图loan_df。


首先,corr()调用该方法loan_df计算相关矩阵。该矩阵包含 DataFrame 中所有列之间的成对相关性。


接下来,heatmap()调用 Seaborn 库中的函数,将相关矩阵作为输入。annot=True参数将相关系数添加到热图单元格,cmap="coolwarm"参数设置热图的配色方案。


最后,show()调用plt对象上的方法来显示热图。
  1. 了解贷款用途分布。
sns.countplot(x="purpose", data=loan_df)
plt.xticks(rotation=90)
plt.show()

此代码使用 seaborn 库创建“loan_df”数据框中“purpose”列的计数图。计数图显示“purpose”列中每个唯一值的频率。


该sns.countplot()函数接受两个参数:“x”和“data”。 “x”指定要绘制的列,“data”指定要使用的数据框。


该plt.xticks(rotation=90)函数将 x 轴标签旋转 90 度,以防止标签重叠。


最后plt.show()显示情节。
  1. 了解按贷款用途划分的利率分布。

sns.boxplot(x="purpose", y="int.rate", data=loan_df)
plt.xticks(rotation=90)
plt.show()

  • 此代码使用 Seaborn 库创建贷款数据集 (loan_df) 中每种用途 (x 轴) 的利率 (y 轴) 的箱线图。
  • 第一行指定了绘图中要使用的 x 和 y 变量,以及要使用的数据集。
  • 第二行将 x 轴标签旋转 90 度,以使其更易于阅读。
  • 第三行显示情节。

特征工程

我们将执行特征工程来简化预处理任务,而不是预处理和清理数据。 

后续提示“编写 Python 代码来执行特征工程”

我们确实得到了正确的解决方案,但是其中包含不相关的代码,因此我们不得不编写更新提示来修改代码。 

更新提示“仅添加特征工程部分。”

# Perform feature engineering
loan_df["installment_to_income_ratio"] = (
loan_df["installment"] / loan_df["log.annual.inc"]
)
loan_df["credit_history"] = (loan_df["delinq.2yrs"] + loan_df["pub.rec"]) / loan_df[
"fico"
]


此代码对名为的 DataFrame 执行特征工程loan_df。
第一行通过将“installment”列除以“log.annual.inc”列来创建一个名为“installment_to_income_ratio”的新列。此比率表示借款人的收入中用于偿还贷款分期付款的百分比。
第二行通过添加“delinq.2yrs”和“pub.rec”列并将结果除以“fico”列,创建了一个名为“credit_history”的新列。该比率表示借款人的信用历史与其 FICO 分数的关系。
总体而言,这些新功能可用于更好地了解借款人的财务状况与其拖欠贷款的可能性之间的关系。

ChatGPT 提出了两个新功能:“installment_to_income_ratio”和“credit_history”。

预处理和平衡数据

再次强调,ChatGPT 了解项目的背景。我们不必再次解释一切。因此,我们只需要求它编写 Python 代码来清理和预处理数据。 

后续提示“现在编写一个 Python 代码来清理和预处理数据集”

  1. 删除不必要的列并将分类变量转换为数值变量。
from sklearn.preprocessing import LabelEncoder, StandardScaler

loan_df = loan_df.drop(['credit.policy', 'days.with.cr.line', 'purpose'], axis=1)

# Convert categorical variables to numerical using LabelEncoder
le = LabelEncoder()
loan_df['not.fully.paid'] = le.fit_transform(loan_df['not.fully.paid'])
  1. 使用标准缩放器缩放数值特征。 
scaler = StandardScaler()
numerical_cols = ['int.rate', 'installment', 'log.annual.inc', 'dti', 'fico', 'revol.bal', 'revol.util', 'inq.last.6mths', 'delinq.2yrs', 'pub.rec','credit_history','installment_to_income_ratio']
loan_df[numerical_cols] = scaler.fit_transform(loan_df[numerical_cols])
  1. 使用 imblearn 的过采样方法处理类不平衡。 
from imblearn.over_sampling import SMOTE

sm = SMOTE(random_state=42)

X = loan_df.drop('not.fully.paid', axis=1)
y = loan_df['not.fully.paid']

X_resampled, y_resampled = sm.fit_resample(X, y)

loan_df = pd.concat([X_resampled, y_resampled], axis=1)
loan_df['not.fully.paid'].value_counts()

我们可以看到,我们已经成功平衡了班级。 

0    8045
1 8045
Name: not.fully.paid, dtype: int64

模型选择

在这一部分中,我们要求 ChatGPT 在各种模型上训练数据以完成模型选择任务。  

后续提示“编写一个用于模型选择的后续 Python 代码。尝试决策树、随机森林、逻辑回归或支持向量机 (SVM)。注意:仅包括模型选择部分。”

它生成了 Python 脚本,将数据集分成训练和测试,并在指定的模型上训练数据集以显示准确性指标。

from sklearn.model_selection import train_test_split

# Split the dataset into training and testing sets
X = loan_df.drop('not.fully.paid', axis=1)
y = loan_df['not.fully.paid']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# Fit and evaluate decision tree classifier
dt = DecisionTreeClassifier(random_state=42)
dt.fit(X_train, y_train)
dt_score = dt.score(X_test, y_test)
print("Decision Tree Classifier Accuracy: {:.2f}%".format(dt_score*100))

# Fit and evaluate random forest classifier
rf = RandomForestClassifier(random_state=42)
rf.fit(X_train, y_train)
rf_score = rf.score(X_test, y_test)
print("Random Forest Classifier Accuracy: {:.2f}%".format(rf_score*100))

# Fit and evaluate logistic regression classifier
lr = LogisticRegression(random_state=42)
lr.fit(X_train, y_train)
lr_score = lr.score(X_test, y_test)
print("Logistic Regression Classifier Accuracy: {:.2f}%".format(lr_score*100))

# Fit and evaluate support vector machine classifier
svm = SVC(random_state=42)
svm.fit(X_train, y_train)
svm_score = svm.score(X_test, y_test)
print("Support Vector Machine Classifier Accuracy: {:.2f}%".format(svm_score*100))

随机森林算法的表现明显优于其他模型。  

Decision Tree Classifier Accuracy: 81.21%
Random Forest Classifier Accuracy: 89.14%
Logistic Regression Classifier Accuracy: 61.32%
Support Vector Machine Classifier Accuracy: 66.54%

超参数调整和模型评估 

我们将选择性能更好的模型并进行模型评估。我们指定使用准确率、精确率、召回率和 F1 分数作为指标,并进行交叉验证以确保模型稳定性。

后续提示“选择 RandomForestClassifier 并编写 Python 代码进行模型评估。使用准确率、精确率、召回率和 F1 分数作为指标,并进行交叉验证,以确保模型不会过度拟合训练数据。”

我们将更新 Python 以添加超参数调整任务并保存性能最佳的模型。 

更新提示“在上述代码中还包括超参数调整,并保存性能最佳的模型”

代码的最终版本使用 GridSearchCV 进行超参数调整,具有五个交叉验证分割,并使用 f1 度量进行评估以找到最佳超参数。 

之后,ChatGPT 自动添加了在测试集上选择最佳模型进行模型评估的代码,并显示表现最佳的超参数。 

from sklearn.model_selection import GridSearchCV
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
# Define the parameter grid for hyperparameter tuning
param_grid = {
'n_estimators': [100, 200, 300],
'max_depth': [10, 20, 30, None],
'min_samples_split': [2, 5, 10],
'min_samples_leaf': [1, 2, 4]
}

# Perform grid search with cross-validation to find the best hyperparameters
grid_search = GridSearchCV(rf, param_grid, cv=5, scoring='f1')
grid_search.fit(X_train, y_train)

# Get the best model and its hyperparameters
best_model = grid_search.best_estimator_
best_params = grid_search.best_params_

# Evaluate the best model on the testing set
y_pred = best_model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)

# Print the results
print("Random Forest Classifier Evaluation Results:")
print("Accuracy: {:.2f}%".format(accuracy * 100))
print("Precision: {:.2f}%".format(precision * 100))
print("Recall: {:.2f}%".format(recall * 100))
print("F1 Score: {:.2f}%".format(f1 * 100))
print("Best hyperparameters:", best_params)

我们有一个稳定的模型,准确率为 89.35。准确率和召回率都差不多。 

Random Forest Classifier Evaluation Results:
Accuracy: 89.35%
Precision: 89.92%
Recall: 88.33%
F1 Score: 89.12%
Best hyperparameters: {'max_depth': None, 'min_samples_leaf': 1, 'min_samples_split': 2, 'n_estimators': 300}

最后,我们将使用 joblib 保存模型。 

import joblib
# Save the best model to disk
joblib.dump(best_model, 'loan_classifier.joblib')

您可以在此 DataLab 工作簿中找到带有输出的源代码;您可以轻松创建自己的副本以在浏览器中编辑和运行代码,而无需在计算机上安装任何东西。 

使用 Gradio 创建 Web 应用程序

现在到了最有趣的部分。我们将仅使用提示来创建一个完全可定制的 Web 应用程序,该应用程序将接受数字输入并使用机器学习模型显示结果。 

ChatGPT 已经知道上下文,所以我们只需要让它为贷款数据分类器编写一个 Gradio 网络应用程序。 

后续提示“编写 Python 代码来创建用于贷款数据分类器的 Gradio Web 应用程序。我们不使用列 [‘credit.policy'、'days.with.cr.line'、'purpose']。”

要求 ChatGPT 仅包含 Gradio 应用程序部分,而不是训练和推理脚本。 

更新提示“仅包含 gradio 应用程序部分。”

我们得到的代码显示了预测类别概率,并且我们想要显示分类标签。 

更新提示“修改代码以显示分类而不是类概率。”

运行代码后,我们看到了多个警告和错误。您可以通过向 ChatGPT 提及错误来改进它。 

我们需要了解 ChatGPT 的局限性。它是在旧数据集上训练的,如果你期望它使用最新的 API 更新代码,那你就会碰壁。相反,我们必须阅读 Gradio文档并手动更新代码。 

失败提示“使用来自 gradio.components 的组件更新 Gradio 代码”

在 Gradio 应用程序中,我们正在加载已保存的模型并从用户那里获取输入以显示模型预测。 

通过阅读Gradio 文档了解 Gradio 的工作原理。

import gradio as gr
import joblib
# Load the trained model
model = joblib.load("loan_classifier.joblib")


def predict_loan_status(
int_rate,
installment,
log_annual_inc,
dti,
fico,
revol_bal,
revol_util,
inq_last_6mths,
delinq_2yrs,
pub_rec,
installment_to_income_ratio,
credit_history,
):
input_dict = {
"int.rate": int_rate,
"installment": installment,
"log.annual.inc": log_annual_inc,
"dti": dti,
"fico": fico,
"revol.bal": revol_bal,
"revol.util": revol_util,
"inq.last.6mths": inq_last_6mths,
"delinq.2yrs": delinq_2yrs,
"pub.rec": pub_rec,
"installment_to_income_ratio": installment_to_income_ratio,
"credit_history": credit_history,
}
# Convert the dictionary to a 2D array
input_array = [list(input_dict.values())]
prediction = model.predict(input_array)[0]

if prediction == 0:
return "Loan fully paid"
else:
return "Loan not fully paid"


inputs = [
gr.Slider(0.06, 0.23, step=0.01, label="Interest Rate"),
gr.Slider(100, 950, step=10, label="Installment"),
gr.Slider(7, 15, step=0.1, label="Log Annual Income"),
gr.Slider(0, 40, step=1, label="DTI Ratio"),
gr.Slider(600, 850, step=1, label="FICO Score"),
gr.Slider(0, 120000, step=1000, label="Revolving Balance"),
gr.Slider(0, 120, step=1, label="Revolving Utilization"),
gr.Slider(0, 10, step=1, label="Inquiries in Last 6 Months"),
gr.Slider(0, 20, step=1, label="Delinquencies in Last 2 Years"),
gr.Slider(0, 10, step=1, label="Public Records"),
gr.Slider(0, 5, step=0.1, label="Installment to Income Ratio"),
gr.Slider(0, 1, step=0.01, label="Credit History"),
]
outputs = [gr.Label(num_top_classes=2)]

title = "Loan Approval Classifier"
description = (
"Enter the details of the loan applicant to check if the loan is approved or not."
)
gr.Interface(
fn=predict_loan_status,
inputs=inputs,
outputs=outputs,
title=title,
description=description,
).launch()

您可以将上述代码保存在“app.py”文件中,并通过在终端中运行“python app.py”脚本在浏览器中启动该应用程序。 

作者的 Gif | 贷款审批分类器应用程序

尽管我们的应用程序运行良好,但 ChatGPT 完全忽略了我们已经缩放了数值特征。因此,您可以返回并保存标准标量参数,而不必要求更新代码。 

scalar = joblib.load('std_scaler.bin')

之后,使用 joblib 在您的应用程序中加载标量。

input_array = [list(input_dict.values())]
scaled_array = scalar.transform(input_array)
prediction = model.predict(scaled_array)[0]

那么,我们为什么要手动执行此操作?如果你要求 ChatGPT 修改一行,它可能会修改整个代码甚至变量名称。 

是的,ChatGPT 并不完美,它永远不会取代开发人员。 

在 Spaces 上部署 Web 应用程序

您可以简单地让 ChatGPT 教您在 Hugging Face Spaces 上部署 gradio 应用程序的简单方法,它会列出必要的步骤。 

提示“如何将 gradio 应用程序部署到 huggingface 空间。”

  1. 进入Hugging Face网站,点击左上角的头像,选择“新空间”选项。  
  1. 添加名称和许可证类型以创建应用程序存储库。 
  2. 单击“文件和版本”选项卡+ 添加文件>上传文件以将文件添加到存储库。 
  3. 拖动 app.py、模型和缩放器文件并单击“将更改提交到主”按钮,并使用提交消息保存提交。类似于 Git。

如果您遇到运行时错误,那是因为您忘记添加 requirements.txt 文件。选择“文件和版本”选项卡 > + 添加文件 > 创建新文件,然后添加文件名和带有版本的 Python 库,如下所示。 

您的应用已准备就绪。您可以使用滑块更改输入并预测客户是否应该获得贷款。 

您可以尝试kingabzpro 在 Hugging Face Space上的现场演示。

图片来自作者 |贷款分类器

编写有效 ChatGPT 提示的技巧

在实际项目中使用即时工程时,它很棘手。我们需要了解我们可以做什么或必须在哪里介入以纠正 ChatGPT 的规则。 

以下是一些关于如何在不影响项目的情况下改善 ChatGPT 体验的提示。

  1. 始终写出清晰简洁的提示。确保在开始时详细解释您需要的一切。
  2. 创建项目历史记录。ChatGPT 是一个聊天机器人,因此为了让它有效地理解上下文,你需要建立历史记录。 
  3. 继续尝试。编写提示没有标准的方法。您需要从基本提示开始,然后通过编写后续更新提示来不断改进匹配。  
  4. 提及代码错误。如果您在本地机器上运行代码并引发错误,请尝试在后续提示中提及错误。ChatGPT 将立即从错误中吸取教训并提出更好的解决方案。 
  5. 手动进行更改。ChatGPT 是在旧数据上进行训练的,如果你期望它能提出新的想法或新的 API 命令,那你将会失望。尽可能尝试手动更改代码,因为生成的代码并不完美。 
  6. 将其用于常见任务。如果您请求常见任务,使用 ChatGPT 成功的机会更大。
  7. 用它来学习新东西。总是要求 ChatGPT 解释新事物或“如何做”教程。它会为你提供完成工作的简单步骤列表。如果你有学习障碍,它会很有帮助。 

结论

开发贷款审批分类器是使用 ChatGPT 进行数据科学项目的众多示例之一。我们可以使用它来生成合成数据、运行 SQL 查询、创建数据分析报告、进行机器学习研究等等。生成式人工智能将继续存在,它将使我们的生活更轻松。您无需花费数周和数月的时间在一个项目上,而是可以在数小时内开发、测试和部署数据科学应用程序。 

在本教程中,我们学习了使用 ChatGPT 进行项目规划、数据分析、数据清理和预处理、模型选择、超参数优化以及创建和部署 Web 应用程序。 

使用 ChatGPT 有一个问题。您需要具有统计分析和 Python 编码经验,才能理解项目中的不同任务;没有它,您就是盲目行事。通过学习Python 数据科学家职业轨迹开始您的数据科学之旅,并获得成为数据科学家所需的职业建设技能。 

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

You May Also Like