在绘制学习曲线以查看模型构建的进展时,我发现验证准确度曲线从一开始就是一条直线。我原本以为可能是由于将数据分成训练集和验证集时出现的错误所致,但当我重复这个过程100次时,得到的图形大致相同。
我该如何解读这个现象?这是怎么回事?我计算准确度得分的方法有错误吗?
此外,准确度一开始就不高,我怀疑我的模型存在欠拟合问题,有没有明显的方法可以改进它?(我无法获取更多数据,所以特征工程是解决方案吗?)
我使用以下代码来计算准确度。
def learning_curve(): X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.33) training_sizes = (np.linspace(0.1, 1.0, 100) * len(X_train)).astype(int) train_accuracy = [] valid_accuracy = [] clf = LogisticRegression(solver='liblinear') for size in training_sizes: clf.fit(X_train.iloc[:size], y_train.iloc[:size]) train_accuracy.append(clf.score(X_train.iloc[:size], y_train.iloc[:size])) valid_accuracy.append(clf.score(X_valid, y_valid)) return training_sizes, train_accuracy, valid_accuracy training_scores = []cross_val_scores = [] for i in range(num_iter): sizes, train_score, cross_valid_score = learning_curve() training_scores.append(train_score) cross_val_scores.append(cross_valid_score) train_std = np.std(training_scores, axis=0)train_mean = np.mean(training_scores, axis=0)cv_std = np.std(cross_val_scores, axis=0)cv_mean = np.mean(cross_val_scores, axis=0) plt.plot(sizes, train_mean, '--', color="b", label="Training score") plt.plot(sizes, cv_mean, color="g", label="Cross validation score") plt.fill_between(sizes, train_mean - train_std, train_mean + train_std, color='gray')plt.fill_between(sizes, cv_mean - cv_std, cv_mean + cv_std, color='gray')
这段代码生成以下图表:
任何帮助都将不胜感激。谢谢你。
回答:
首先,尽管您的实现看起来是正确的,但您应该验证learning_curve
的实现。一个快速验证的方法是将其与Scikit-Learn已有的learning_curve
函数进行比较(附注:如果我是您,我会直接使用Scikit-Learn的版本,不必重新发明轮子)。
由于您没有提供任何数据,我不得不创建一些分类数据集。
X, y = make_classification(n_samples=1000, n_features=5, n_informative=5, n_redundant=0, n_repeated=0, n_classes=2, shuffle=True, random_state=2020)
结果表明您的实现是正确的(为了清晰起见,去除了偏差):
现在我们确定了实现的正确性,问题可能出在您的数据集上。我们需要领域知识来进行一些探索性数据分析(EDA)。
您的数据可能包含冗余信息,增加了很多噪音。
如果我重复同样的实验,但这次我创建了大量冗余数据
X, y = make_classification(n_samples=1000, n_features=5, n_informative=2, n_redundant=3, n_repeated=0, n_classes=2, shuffle=True, random_state=2020)
您会看到几乎与您的结果相似的模式出现:
注意,您得到的分数并不低,准确度>=90%被认为是非常好的。