我在尝试使用Python训练一个决策树分类器。我使用MinMaxScaler()
来缩放数据,并使用f1_score
作为我的评估指标。奇怪的是,我注意到我的模型每次运行时都会以某种模式给出不同的结果。
我的代码中的data
是一个(2000, 7)
的pandas.DataFrame
,有6个特征列,最后一列是目标值。第1、3和5列是分类数据。
以下是我对数据进行预处理和格式化的代码:
import numpy as npimport pandas as pdfrom sklearn.tree import DecisionTreeClassifierfrom sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import LabelEncoderfrom sklearn.preprocessing import OneHotEncoderfrom sklearn.preprocessing import MinMaxScalerfrom sklearn.metrics import f1_score# Data Preprocessing Step# =============================================================================data = pd.read_csv("./data/train.csv")X = data.iloc[:, :-1]y = data.iloc[:, 6]# Choose which columns are categorical data, and convert them to numeric data.labelenc = LabelEncoder()categorical_data = list(data.select_dtypes(include='object').columns)for i in range(len(categorical_data)): X[categorical_data[i]] = labelenc.fit_transform(X[categorical_data[i]])# Convert categorical numeric data to one-of-K data, and change y from Series to ndarray.onehotenc = OneHotEncoder()X = onehotenc.fit_transform(X).toarray()y = y.valuesX_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2)min_max_scaler = MinMaxScaler()X_train_scaled = min_max_scaler.fit_transform(X_train)X_val_scaled = min_max_scaler.fit_transform(X_val)
接下来的代码是用于实际决策树模型训练的:
dectree = DecisionTreeClassifier(class_weight='balanced')dectree = dectree.fit(X_train_scaled, y_train)predictions = dectree.predict(X_val_scaled)score = f1_score(y_val, predictions, average='macro')print("Score is = {}".format(score))
我得到的输出(即得分)会有所不同,但呈现出一种模式。例如,它会在0.39
和0.42
的范围内循环变化。
在某些迭代中,我甚至会收到UndefinedMetricWarning
,它声称“在没有预测样本的标签中,F分数未定义并被设置为0.0。”
通过在这个社区和Google上搜索,我已经了解了UndefinedMetricWarning
的含义。我猜我的两个问题可以整理为:
-
为什么我的输出在每次迭代中都会变化?在预处理阶段是否有我不知道的事情发生?
-
我还尝试在其他数据分割上使用F分数,但总是会得到警告。这是否无法避免?
谢谢你。
回答:
您将数据集分为训练和测试集,这会随机划分用于训练和测试的集合。因此,当您每次用不同的训练数据训练模型,并用不同的测试数据进行测试时,您会得到一系列的F分数,这取决于模型的训练效果如何。
为了每次运行时复制结果,请使用random_state
参数。它将保持一个随机数状态,这将使您每次运行时获得相同的随机数。这表明随机数是以相同的顺序生成的。这个参数可以是任何数字。
#train test splitX_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=13)#Decision tree modeldectree = DecisionTreeClassifier(class_weight='balanced', random_state=2018)