KNN在Cifar上的应用
def getXmean(X_train): X_train = np.reshape(X_train, (X_train.shape[0], -1)) # 将图片从二维展开为一维 mean_image = np.mean(X_train, axis=0) # 求出训练集所有图片每个像素位置上的平均值 return mean_image def centralized(X_test,mean_image): X_test = np.reshape(X_test, (X_test.shape[0], -1)) # 将图片从二维展开为一维 X_test = X_test.astype(np.float) X_test -= mean_image # 减去均值图像,实现零均值化???? return X_test X_train = train_loader.dataset.train_data mean_image = getXmean(X_train) X_train = centralized(X_train,mean_image) y_train = train_loader.dataset.train_labels X_test = test_loader.dataset.test_data[:100] X_test = centralized(X_test,mean_image) y_test = test_loader.dataset.test_labels[:100] num_test = len(y_test) y_test_pred = kNN_classify(6, 'M', X_train, y_train, X_test)#这里并没有使用封装好的类 是因为没有定义一个新的类来存放方法吗 num_correct = np.sum(y_test_pred == y_test) accuracy = float(num_correct) / num_test print('Got %d / %d correct => accuracy: %f' % (num_correct, num_test, accuracy))
X_train.shape[0]
:这表示X_train
的第一个维度的大小,即它的行数。在机器学习和数据处理的上下文中,这通常代表样本的数量。-1
:在numpy
的reshape
函数中,-1
是一个特殊的值,它告诉numpy
自动计算该维度的大小,以保持数组中元素的总数不变。这意味着,如果你指定了除-1
之外的其他所有维度的大小,numpy
将计算出-1
所在维度的大小,以确保重塑后的数组与原始数组具有相同数量的元素。
模型参数调优
机器学习方法(深度学习是机器学习中的一种)往往涉及很多参数甚至超参数,此实践过程中需要对这些参数进行适当地选择和调整。
对于KNN算法来说,k就是需要调整的超参数。
有一种更专业的穷举调参方法称为GridSearch, 即在所有候选的参数中,通过循环遍历,尝试每一种的可能性,表现最好的参数就是最终的结果。
那么选用哪些数据集进行调参呢? k=1 总是最好的??
方法一,选择整个数据集进行测试。这种方法有一个非常明显的问题,那就是设定 k=1 总是最好的,因为每个测试样本的位置总是与整个训练集中的自己最接近,
Your Dataset
方法二,将整个数据集拆分成训练集和测试集,然后在测试集中选择合适的超参数。这里也会存在一个问题,那就是不清楚这样训练出来的算法模型对于接下来的新的测试数据的表现会如何
train
test
方法三,将整个数据集拆分成训练集、验证集和测试集,然后在验证集中选择合适的超参数,最后在测试集上进行测试。这个方法相对来说比之前两种方法好很多,也是在实践中经常使用的方法
train validation test
方法四,使用交叉验证,将数据分成若干份,将其中的各份作为验证集之后给出平均准确率,最后将评估得到的合适的超参数在测试集中进行测试。这个方法更加严谨,但实践中常在较小的数据集上使用
fold 1 fold 2 fold 3 fold 4 fold 5 test
fold 1 fold 2 fold 3 fold 4 fold 5 test
fold 1 fold 2 fold 3 fold 4 fold 5 test
class Knn: def __init__(self): pass def fit(self,X_train,y_train): #定义了一个封装吗 self.Xtr = X_train self.ytr = y_train def predict(self,k, dis, X_test): assert dis == 'E' or dis == 'M', 'dis must E or M' num_test = X_test.shape[0] # 测试样本的数量 labellist = [] # 使用欧拉公式作为距离度量 if (dis == 'E'): for i in range(num_test): distances = np.sqrt(np.sum(((self.Xtr - np.tile(X_test[i], (self.Xtr.shape[0], 1))) ** 2), axis=1)) nearest_k = np.argsort(distances) 从小到大排列 topK = nearest_k[:k] classCount = {} for i in topK: classCount[self.ytr[i]] = classCount.get(self.ytr[i], 0) + 1
-
self.ytr[i]
:访问self.ytr
列表(或数组)中索引为i
的元素,即当前训练样本的标签。 classCount.get(self.ytr[i], 0)
:尝试从classCount
字典中获取键为self.ytr[i]
的值。如果self.ytr[i]
不在classCount
的键中,则使用默认值0
+ 1
:将上一步得到的值(无论是从字典中检索到的还是默认值0
)增加1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) #降序sorted()
函数是 Python 的内置函数,用于对可迭代对象(如列表、元组、字典的项等)进行排序,并返回一个新的列表,其中包含已排序的元素。与列表的.sort()
方法不同,sorted()
函数不会修改原始的可迭代对象,而是返回一个新的列表。
labellist.append(sortedClassCount[0][0]) return np.array(labellist) # 使用曼哈顿公式作为距离度量 if (dis == 'M'): for i in range(num_test): # 按照列的方向相加,其实就是行相加 distances = np.sum(np.abs(self.Xtr - np.tile(X_test[i], (self.Xtr.shape[0], 1))), axis=1) nearest_k = np.argsort(distances) topK = nearest_k[:k] classCount = {} for i in topK: classCount[self.ytr[i]] = classCount.get(self.ytr[i], 0) + 1 sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) labellist.append(sortedClassCount[0][0]) return np.array(labellist)
sorted()
函数的基本语法如下:
sorted(iterable, *, key=None, reverse=False)
iterable
:要排序的可迭代对象。key
:一个函数,用于从每个元素中提取一个用于比较的关键字。默认为None
,表示直接比较元素本身。reverse
:一个布尔值,指定排序是升序(False
)还是降序(True
)。默认为False
。
准备验证集与测试集数据,使用交叉验证,在选择超参数阶段不需要使用X-TEST与Y-TEST的使用
常见的超参数包括:
-
学习率(Learning Rate):控制模型在训练过程中权重更新的步长大小。学习率太小会导致训练过程缓慢,而学习率太大则可能导致训练过程不稳定,甚至无法收敛。
-
批量大小(Batch Size):在每次权重更新时使用的样本数量。批量大小的选择会影响模型的训练速度和泛化能力。较小的批量大小可能导致训练过程更加不稳定,但有助于模型更快地适应训练数据的变化。
-
迭代次数/训练周期(Epochs):整个训练数据集被遍历的次数。迭代次数太少可能导致模型欠拟合,而迭代次数太多则可能导致模型过拟合。
-
正则化参数(Regularization Parameters):用于控制模型复杂度的参数,如L1正则化、L2正则化中的系数。正则化参数有助于防止模型过拟合。
-
网络架构参数:在神经网络中,超参数还包括网络的层数、每层的神经元数量、激活函数类型等。这些参数的选择对模型的性能有着重要影响。
-
优化器参数:如动量(Momentum)、学习率衰减(Learning Rate Decay)等,这些参数控制优化算法的行为,进而影响模型的训练过程。
-
dropout比率:在神经网络中,dropout是一种正则化技术,用于减少神经元之间的共适应性,从而提高模型的泛化能力。dropout比率是指在训练过程中随机丢弃神经元的比例。
X_train = train_loader.dataset.train_data X_train = X_train.reshape(X_train.shape[0],-1) mean_image = getXmean(X_train) X_train = centralized(X_train,mean_image) y_train = train_loader.dataset.train_labels y_train = np.array(y_train) X_test = test_loader.dataset.test_data X_test = X_test.reshape(X_test.shape[0],-1) X_test = centralized(X_test,mean_image) y_test = test_loader.dataset.test_labels y_test = np.array(y_test) print(X_train.shape) print(y_train.shape) print(X_test.shape) print(y_test.shape)
num_folds = 5
k_choices = [1, 3, 5, 8, 10, 12, 15, 20]#k的值一般选择1~20以内
num_training=X_train.shape[0]
X_train_folds = []
y_train_folds = []
indices = np.array_split(np.arange(num_training), indices_or_sections=num_folds) # 把下标分成5个部分
for i in indices:
X_train_folds.append(X_train[i])
y_train_folds.append(y_train[i])
k_to_accuracies = {}
for k in k_choices:
# 进行交叉验证
acc = []
for i in range(num_folds):
x = X_train_folds[0:i] + X_train_folds[i+1:] #训练集不包括验证集
x = np.concatenate(x, axis=0) # 使用concatenate将4个训练集拼在一起
y = y_train_folds[0:i] + y_train_folds[i+1:]
y = np.concatenate(y) # 对label使用同样的操作
test_x = X_train_folds[i] #单独拿出验证集
test_y = y_train_folds[i]
classifier = Knn() # 定义model
classifier.fit(x, y) # 将训练集读入
#dist = classifier.compute_distances_no_loops(test_x) # 计算距离矩阵
y_pred = classifier.predict(k,'M',test_x) # 预测结果
accuracy = np.mean(y_pred == test_y) # 计算准确率
acc.append(accuracy)
k_to_accuracies[k] = acc # 计算交叉验证的平均准确率
# 输出准确度
for k in sorted(k_to_accuracies):
for accuracy in k_to_accuracies[k]:
print('k = %d, accuracy = %f' % (k, accuracy))
# plot the raw observations
import matplotlib.pyplot as plt
for k in k_choices:
accuracies = k_to_accuracies[k]
plt.scatter([k] * len(accuracies), accuracies)
# plot the trend line with error bars that correspond to standard deviation
accuracies_mean = np.array([np.mean(v) for k,v in sorted(k_to_accuracies.items())])
accuracies_std = np.array([np.std(v) for k,v in sorted(k_to_accuracies.items())])
plt.errorbar(k_choices, accuracies_mean, yerr=accuracies_std)
plt.title('Cross-validation on k')
plt.xlabel('k')
plt.ylabel('Cross-validation accuracy')
plt.show()
标签:图像识别,fold,day4,np,train,深度,test,self,mean From: https://www.cnblogs.com/candice1/p/18328767