notebook代码
# import package
import numpy as np
import pickle
import matplotlib.pyplot as plt
# load train and test data
# batches_meta = open('F:\PycharmProjects\cs231n\homework_1_SVM\cifar-10-batches-py\\batches.meta','rb')
# batches_meat_object = pickle.load(batches_meta,encoding='bytes')
# print(type(batches_meat_object)) # 一个字典格式
# print(batches_meat_object)
train_data = []
train_label = []
# 加载训练数据集,每个batch中有10000条数据,分开放的,现在把他们合并起来
for i in range(1,6):
file_object = open('work/CIFAR10/data_batch_'+str(i),'rb')
data_object = pickle.load(file_object,encoding='bytes') # 字典格式
# print(type(data_object[b'data'][2][3]))
for line in data_object[b'data']:
train_data.append(line)
for line in data_object[b'labels']:
train_label.append(line)
# notice there,train_data and train_label are the structure of python's list,you should transport to numpy's array
# 这里注意数据集中给的是 整形数据,不注意的话后面会出现错误 使用numpy.array.astype('float')方法可以直接整体转换,还有注意将python list转换为numpy array型
train_data = np.array(train_data).astype("float")
train_label = np.array(train_label)
# print(train_label)
print("train_data shape:"+str(train_data.shape))
print("train_label shape:"+str(train_label.shape))
# 加载测试集数据
test_data = []
test_label = []
test_file = open('work/CIFAR10/test_batch','rb')
test_file_object = pickle.load(test_file,encoding='bytes')
# print(test_file_object)
for line in test_file_object[b'data']:
test_data.append(line)
for line in test_file_object[b'labels']:
test_label.append(line)
test_data = np.array(test_data).astype("float")
test_label = np.array(test_label)
print("test_data shape:"+str(test_data.shape))
print("test_label shape:"+str(test_label.shape))
# print(test_label.ndim)
# 数据预处理
# np.mean()
mean_image = np.mean(train_data,axis=0)
train_data -=mean_image
# train_label -=mean_image # TODO
test_data -=mean_image
# test_label -=mean_image
# 首先,np.ones()可以创建元素值为1的数组,几维都可以,二维的时候就是用[]来括起来,还可以利用第二个参数来指定元素的类型,默认创建的是float型
train_data = np.hstack((train_data,np.ones([train_data.shape[0],1]))) # np.hstack()值得熟悉一下怎么使用的 注意两个array要再用一个括号括起来
# train_label = np.hstack(train_label,np.ones([train_label.shape[0],1]))
test_data = np.hstack((test_data,np.ones([test_data.shape[0],1])))
# test_label = np.hstack(test_label,np.ones([test_label.shape[0],1]))
print(str(train_data.shape))
class LinearSVM:
def __init__(self):
self.W = None
def loss(self, X, y, reg):
"""
Structured SVM loss function, vectorized implementation.
Inputs and outputs are the same as svm_loss_naive.
"""
loss = 0.0
dW = np.zeros(self.W.shape) # initialize the gradient as zero
num_train = X.shape[0]
scores = X.dot(self.W)
# print("test:")
# print(range(num_train))
# print(list(y))
# print(scores[range(num_train), list(y)])
#这里的code不熟悉还是不太容易理解,
# print("scores维度:"+str(scores.shape))
# 下面这句代码,还真的挺难懂的,确实把numpy用的很熟练
# scores是200*10的,y 是100*1 维的,他们都是numpy.array类型的,然后scores[range(num_train),list(y)],[]里面两个列表,看了半天,他是把scores这个二维数组中
# 每行正确分类的分数给单独拿出来放到一维array中,这时候是1*200的,最后再通过一个reshape 将其转换成200*1的,后面和非正确的分数进行减法运算,太牛逼的表达了
correct_class_score = scores[range(num_train), list(y)].reshape(-1,1) # (N,1) (1,-1)是二维内部转换成一行,(-1,1)转换成1列
margin = np.maximum(0, scores - correct_class_score + 1)
margin[range(num_train), list(y)] = 0 # 正确分类的分数值在上面的运算之后都变成了1,现在把他们都变成0
loss = np.sum(margin) / num_train + 0.5 * reg * np.sum(self.W * self.W) #后面是正则化惩罚项
num_classes = self.W.shape[1]
inter_mat = np.zeros((num_train, num_classes))
inter_mat[margin > 0] = 1
inter_mat[range(num_train), list(y)] = 0
inter_mat[range(num_train), list(y)] = -np.sum(inter_mat, axis=1)
dW = (X.T).dot(inter_mat)
dW = dW/num_train + reg*self.W
return loss, dW
def train(self, X, y, learning_rate=1e-3, reg=1e-5, num_iters=100,
batch_size=200, verbose=False):
"""
Train this linear classifier using stochastic gradient descent. SGD
Inputs:
- X: A numpy array of shape (N, D) containing training data; there are N
training samples each of dimension D.
- y: A numpy array of shape (N,) containing training labels; y[i] = c
means that X[i] has label 0 <= c < C for C classes.
- learning_rate: (float) learning rate for optimization.
- reg: (float) regularization strength.
- num_iters: (integer) number of steps to take when optimizing
- batch_size: (integer) number of training examples to use at each step.
- verbose: (boolean) If true, print progress during optimization.
Outputs:
A list containing the value of the loss function at each training iteration.
"""
num_train, dim = X.shape
num_classes = np.max(y) + 1 # assume y takes values 0...K-1 where K is number of classes
if self.W is None:
# lazily initialize W
self.W = 0.001 * np.random.randn(dim, num_classes) #权重的初始化
# Run stochastic gradient descent to optimize W
loss_history = []
for it in range(num_iters):
X_batch = None
y_batch = None
idx_batch = np.random.choice(num_train, batch_size, replace = False) # 从num_train 中随机选择batch_size个出来,replace表示抽样之后是否放回,true为放回
X_batch = X[idx_batch]
y_batch = y[idx_batch]
# evaluate loss and gradient
loss, grad = self.loss(X_batch, y_batch, reg)
loss_history.append(loss)
self.W -= learning_rate * grad
if verbose and it % 100 == 0:
print('iteration %d / %d: loss %f' % (it, num_iters, loss))
return loss_history
def predict(self, X):
"""
Use the trained weights of this linear classifier to predict labels for
data points.
Inputs:
- X: A numpy array of shape (N, D) containing training data; there are N
training samples each of dimension D.
Returns:
- y_pred: Predicted labels for the data in X. y_pred is a 1-dimensional
array of length N, and each element is an integer giving the predicted
class.
"""
y_pred = np.zeros(X.shape[0])
scores = X.dot(self.W)
y_pred = np.argmax(scores, axis = 1)
return y_pred
svm = LinearSVM()
loss_hist = svm.train(train_data, train_label, learning_rate=1e-7, reg=2.5e4,
num_iters=1500, verbose=True)
plt.plot(loss_hist)
plt.xlabel('Iteration number')
plt.ylabel('Loss value')
plt.show()
y_train_pred = svm.predict(train_data)
print("train accuracy: %f" % (np.mean(train_label == y_train_pred)))
y_test_pred = svm.predict(test_data)
print('accuracy: %f' % (np.mean(test_label== y_test_pred)))
写代码好难啊,我好菜啊!这里面大多数代码是别人写的
我写不出来,大佬的代码中numpy用的好好啊,我看都看半天,下面在粘贴下自己测试numpy的代码,加深理解。
# 这里测试使用numpy ones和zeros的使用
import numpy as np
a = np.zeros(3) # 默认为float64 位
b = np.zeros([2,3],int) # int表示int 32位
c = np.zeros([3,3],dtype='float32')
d = np.zeros([3,4])
print(a,type(a[1]))
print(b,type(b[1][1]))
print(c,type(c[1][1]))
print(d,type(d[1][1]))
aa = np.ones(3)
print(aa,type(aa[1]))
bbn = np.ones([2,2],dtype='int32')
print(bbn,type(bbn[1][1]))
rs = np.array([[1,2,3],
[2,4,7]])
rs1 = rs.reshape(-1,1) # 内部所有数组成一列
rs2 = rs.reshape(1,-1) # 内部所有数排成一行
# 相当于reshape(-1,1) or reshape(1,-1) 对内部数据的结构进行了转换
# reshape中的参数知道了,其实就是几行几列的意思,第一个如果为-1的话,那么表示的就是其中的元素个数列,也就是变成一列
# 如果是(1,-1)的话,也就是差不多,-1表示自动计算,但是计算出来要可以整除
print(rs1)
print(rs2)
rs3 = rs.reshape(-1,) # 这里只写一个-1竟然变成了一个一维列表而不是二维的了
print(rs3)
rs4 = rs.reshape(2,-1) #这里变换为2行,至于每行几列直接写一个 -1来让他自己计算,但是要能够整除
print(rs4)
add1 = np.array([[1],
[2],
[3]])
add2 = np.array([[1],
[4],
[3]])
print(add1-add2+1) # 这里加一可以直接每个都加上去,之前在写knn的时候减法也是这样的
margin = np.maximum(0,add1-add2+1) # 同理,这里的和0比较大小,也是分别去比较,好几把灵活啊
print(margin)
scores = np.array([[1,2,3,4]])
y = np.array([1,2,3
])
correct_class_score = scores[range(1), list(y)]
print(list(y))
print(str(y.shape))
print(correct_class_score)
想写好代码还是得多动手多写啊,加油