我有一个书籍数据集,我正在尝试选择最佳匹配。我尝试了LinearRegression
、Decisiontree
和Polynomial
,但它们似乎都无法很好地拟合曲线。我已经绘制了三条不同的曲线,其中一条是特征与y_target的关系,下面是这些图表:
曲线1:书籍评分的数量与书籍评分
那么,请告诉我对于这种类型的曲线最适合的模型是什么,或者我应该通过其他方式进行分析?线性回归的输出结果是:
MSE:0.11599130999215618
MAE:0.23
准确度:0.11599130999215622
R2得分:0.08296506346310017
我认为对数模型可能会不错,但它可能会忽略一些数据(每条曲线接近5的值附近的数据)。我对机器学习很新手,所以请至少指导我一下。
这是数据集的链接:https://www.kaggle.com/jealousleopard/goodreadsbooks
数据集的快速浏览:
这是代码:
import pandas as pdimport numpy as npfrom sklearn.preprocessing import StandardScalerfrom sklearn.model_selection import train_test_splitfrom sklearn.linear_model import LinearRegressionfrom sklearn.metrics import r2_score, mean_squared_errorimport matplotlib.pyplot as pltfrom sklearn.tree import DecisionTreeRegressorfrom sklearn.preprocessing import PolynomialFeaturesfrom scipy import statsdf = pd.read_csv("books.csv")def drop_numerical_outliers(df, z_thresh=3): # Constrains will contain `True` or `False` depending on if it is a value below the threshold. constrains = df.select_dtypes(include=[np.number]) \ .apply(lambda x: np.abs(stats.zscore(x)) < z_thresh, reduce=False) \ .all(axis=1) # Drop (inplace) values set to be rejected df.drop(df.index[~constrains], inplace=True)df.drop(['bookID','Unnamed: 10','isbn13','isbn','title','authors'], axis=1, inplace=True)print(df.columns.values)print("Shape After dropping columns: ",df.shape)df.replace(to_replace = 'None', value = '0', inplace=True)df = df[df['# num_pages'] != '0'] print("Shape After Removing Rows with Num_pages 0: ",df.shape)drop_numerical_outliers(df)#print(df['# num_pages'].values[339])print("Shape After Removing outliers: ",df.shape)dummy_cols = ['language_code']df = pd.get_dummies(df, columns=dummy_cols)print("Shape After Categorizing dataset: ",df.shape)#df[(np.abs(stats.zscore(df)) < 3).all(axis=1)] x = df[df.columns.values]x.drop(['average_rating'], axis=1, inplace=True)y = df['average_rating']x = x.apply(pd.to_numeric, errors='coerce')y = y.apply(pd.to_numeric, errors='coerce')x.fillna(0, inplace=True)y.fillna(0, inplace=True)#print(repr(df['# num_pages']))#x = StandardScaler().fit_transform(x)#print(df.head())plt.scatter(x['# num_pages'],y, color = 'blue')plt.xlabel("Number of Pages per Book")plt.ylabel("Ratings")plt.show()x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=4)regr = LinearRegression()#regr = DecisionTreeRegressor(random_state=0 )regr.fit(x_train, y_train)y_hat = regr.predict(x_test)print(y_hat)print(y_test.values)print("MSE: ", mean_squared_error(y_test, y_hat))print("Mean absolute error: %.2f" %np.mean(np.absolute(y_hat - y_test)))print("Accuarcy: ", np.mean((y_hat - y_test)**2))print('R2 score: ', r2_score(y_test, y_hat))
回答:
首先,在机器学习中,你必须非常注意你选择用于训练的特征。在你的例子中,“每本书的页数”并不能真正帮助你,因为如果一本书好,读者并不会在意页数。这个事实在曲线3中得到了进一步的证实,数据在3到5的评分之间非常密集。所以你并不真正需要这个特征。
回到你的问题上,你正在尝试预测书籍的评分。曲线1和2的图表显示,一条曲线无法通过所有点(如果能做到,那将是一个过拟合的模型)。在这种情况下,线性回归会在y轴接近4的值处创建一条直线,因为大多数样本都在那里。
如果你使用不同阶数的多项式回归,它会给你相应阶数的曲线,但仍然无法像你希望的那样通过所有点,而在你的情况下,这甚至不是必要的。
现在重要的是评估指标。你的MAE非常低,这表明你的模型可以做出很好的预测(低MAE表示好结果,高MAE表示坏结果)。但你的R2只有0.082。R2的范围在0到1之间,1表示完美预测(可能显示过拟合),0表示非常差的模型和预测。0.082的值表明在一些测试值中,预测结果与目标值相差甚远。因此,总结结果,你的模型可以给出高准确度的预测,但有时会大幅偏离目标。
在这种情况下,我建议你收集更多相关的特征,然后使用神经网络训练你的模型,以获得更好的模型。
我现在已经分析了这个数据集,这里有几点我想提及。
首先,我绘制了y_test和y_hat(仅限线性回归的预测值)之间的图表:
正如我之前解释的那样,线性回归会在值4附近创建一条直线,你可以看到所有的预测都靠近这条线。因此,对于真实评分为0或5的值,它会产生高预测误差。这就是为什么你的R2得分如此低,而这个低分表明你的特征对于这个模型来说不够好。
如果你访问这个笔记本:https://www.kaggle.com/bellali/select-which-book-to-enjoy你会发现特征与你的目标(书籍评分)之间没有或只有很低的相关性。此外,我也运行了不同的算法,结果很差或相当相似,这进一步证实了特征并不能解释你的目标。
这里要提到的另一件事是,这个数据集仅仅用于探索性目的,而不是用于预测。你可以看到几个使用此数据进行不同类型分析的内核,这就是这个数据集的真正用途。
这是一个典型的“模型的好坏取决于数据”的例子。