目录
8-4 为什么要训练数据集与测试数据集
为什么使用测试数据集
过拟合
模型的泛化能力差
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
def PolynomialRegression(degree):
return Pipeline([
("poly", PolynomialFeatures(degree=degree)),
("std_scaler", StandardScaler()),
("lin_reg", LinearRegression())
])
from sklearn.metrics import mean_squared_error
poly100_reg = PolynomialRegression(degree=100)
poly100_reg.fit(X, y)
y100_predict = poly100_reg.predict(X)
mean_squared_error(y, y100_predict)
机器学习主要解决的是过拟合的问题
模型能力太差,不是为了完全拟合这些数据,应该是模型的泛化能力
train test split的意义
二阶的模型比一阶的模型泛化能力要强
10阶时变小,泛化能力下降了,100时就更明显了
模型复杂度对于不对算法含义不同
knn是k , 多项式回归是n,
对于训练数据就复杂高则准确率会高,但对测试数据就不一样了
过拟合到欠拟合的过程
欠不能表达数据的关系
有眼睛的都是猫或狗,则模型是欠拟合的
毛发是黄色则为过拟合的,太细节的标准做为判断标准
之前的网格搜索一直就是这么干的
8-5 学习曲线05-Learning-Curve
学习曲线
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
train_score = []
test_score = []
for i in range(1, 76):
lin_reg = LinearRegression()
lin_reg.fit(X_train[:i], y_train[:i])
y_train_predict = lin_reg.predict(X_train[:i])
train_score.append(mean_squared_error(y_train[:i], y_train_predict))
y_test_predict = lin_reg.predict(X_test)
test_score.append(mean_squared_error(y_test, y_test_predict))
plt.plot([i for i in range(1, 76)], np.sqrt(train_score), label="train")
plt.plot([i for i in range(1, 76)], np.sqrt(test_score), label="test")
plt.legend()
plt.show()
def plot_learning_curve(algo, X_train, X_test, y_train, y_test):
train_score = []
test_score = []
for i in range(1, len(X_train)+1):
algo.fit(X_train[:i], y_train[:i])
y_train_predict = algo.predict(X_train[:i])
train_score.append(mean_squared_error(y_train[:i], y_train_predict))
y_test_predict = algo.predict(X_test)
test_score.append(mean_squared_error(y_test, y_test_predict))
plt.plot([i for i in range(1, len(X_train)+1)],
np.sqrt(train_score), label="train")
plt.plot([i for i in range(1, len(X_train)+1)],
np.sqrt(test_score), label="test")
plt.legend()
plt.axis([0, len(X_train)+1, 0, 4])
plt.show()
plot_learning_curve(LinearRegression(), X_train, X_test, y_train, y_test)
from sklearn.preprocessing import PolynomialFeatures
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
def PolynomialRegression(degree):
return Pipeline([
("poly", PolynomialFeatures(degree=degree)),
("std_scaler", StandardScaler()),
("lin_reg", LinearRegression())
])
poly2_reg = PolynomialRegression(degree=2)
plot_learning_curve(poly2_reg, X_train, X_test, y_train, y_test)
稳定后两者的间距很大,这样通常就是过拟合的情况,泛化能力 不够
欠拟合训练数据上大
训练的上小,但测试的上大,两者的间距也大
8-6 验证数据集与交叉验证
的训练数据集上误差很好,但测试上不好
所以将数据集分开
这样肯定比只用全为训练数据要好
有了模型后,通过测试数据上效率最好,调试参数,模型在围绕着测试数据集打转,有可能在测试数据集上过拟合
找到训练的模型在已知测试数据集 上过拟合,如通过将数据分为三部分解决
训练好后,模型给验证数据,找到验证数据的好参数模型
测试数据没有用过,完全不知的
这时的问题是随机,数据集的分割,如果有特殊的数据直接影响模型的结果
为了解决这个问题就是交叉验证
把数据分为k分,比如三分
每一个会有一个模型参数,求匀值
from sklearn.neighbors import KNeighborsClassifier
best_k, best_p, best_score = 0, 0, 0
for k in range(2, 11):
for p in range(1, 6):
knn_clf = KNeighborsClassifier(weights="distance", n_neighbors=k, p=p)
knn_clf.fit(X_train, y_train)
score = knn_clf.score(X_test, y_test)
if score > best_score:
best_k, best_p, best_score = k, p, score
print("Best K =", best_k)
print("Best P =", best_p)
print("Best Score =", best_score)
使用交叉验证
默认分为三分,自己实现时先可以用随机的方法来分割数据
best_k, best_p, best_score = 0, 0, 0
for k in range(2, 11):
for p in range(1, 6):
knn_clf = KNeighborsClassifier(weights="distance", n_neighbors=k, p=p)
scores = cross_val_score(knn_clf, X_train, y_train)
score = np.mean(scores)
if score > best_score:
best_k, best_p, best_score = k, p, score
print("Best K =", best_k)
print("Best P =", best_p)
print("Best Score =", best_score)
交叉验证和 结果不一样
可能交叉验证的结果要好,1,因为这可能是 中过拟合test数据集的结构 2,分数低,因为它不过拟合数据一般
交叉验证是为了得到最佳的k和p,然后就能有自己的最好的分类器
回顾网格搜索
默认分为三分,i为9种可能,p为5种可能,即45*3= 135个模型的结果
用三交叉验证的方式得到的结果,用了完全模型没用的数据来衡量模型
from sklearn.model_selection import GridSearchCV
param_grid = [
{
'weights': ['distance'],
'n_neighbors': [i for i in range(2, 11)],
'p': [i for i in range(1, 6)]
}
]
grid_search = GridSearchCV(knn_clf, param_grid, verbose=1)
grid_search.fit(X_train, y_train)
cv参数
把数据分为几分通过CV来决定
留一法Loo-CV