|
import os |
|
from sklearn.preprocessing import OneHotEncoder |
|
import numpy as np |
|
import pickle as pk |
|
|
|
|
|
|
|
def load_batch(file): |
|
with open(file, 'rb') as f: |
|
data_dict = pk.load(f, encoding='bytes') |
|
images = data_dict[b'data'] |
|
labels = data_dict[b'labels'] |
|
images = images.reshape(10000, 3072) |
|
labels = np.array(labels) |
|
return (images / 255), labels |
|
|
|
|
|
def load_data(data_dir): |
|
images_train = [] |
|
labels_train = [] |
|
for i in range(5): |
|
file = os.path.join(data_dir, 'data_batch_%d' % (i + 1)) |
|
print('加载文件:', file) |
|
|
|
images_batch, labels_batch = load_batch(file) |
|
images_train.append(images_batch) |
|
labels_train.append(labels_batch) |
|
|
|
x_train = np.concatenate(images_train) |
|
t_train = np.concatenate(labels_train) |
|
del images_batch, labels_batch |
|
|
|
|
|
x_test, t_test = load_batch(os.path.join(data_dir, 'test_batch')) |
|
return x_train, t_train, x_test, t_test |
|
|
|
|
|
def sigmoid(x): |
|
return 1 / (1 + np.exp(-x)) |
|
|
|
|
|
def sigmoid_grad(x): |
|
return (1.0 - sigmoid(x)) * sigmoid(x) |
|
|
|
|
|
def softmax(x): |
|
if x.ndim == 2: |
|
x = x.T |
|
x = x - np.max(x, axis=0) |
|
y = np.exp(x) / np.sum(np.exp(x), axis=0) |
|
return y.T |
|
|
|
x = x - np.max(x) |
|
return np.exp(x) / np.sum(np.exp(x)) |
|
|
|
|
|
class neuralNetwork: |
|
|
|
def __init__(self, numNeuronLayers, numNeurons_perLayer, learningRate): |
|
self.numNeurons_perLayer = numNeurons_perLayer |
|
self.numNeuronLayers = numNeuronLayers |
|
self.learningRate = learningRate |
|
self.weight = [] |
|
self.bias = [] |
|
for i in range(numNeuronLayers): |
|
self.weight.append( |
|
learningRate * np.random.randn(self.numNeurons_perLayer[i], self.numNeurons_perLayer[i + 1])) |
|
self.bias.append(np.zeros(self.numNeurons_perLayer[i + 1])) |
|
|
|
def predict(self, x): |
|
z = x |
|
|
|
for i in range(self.numNeuronLayers - 1): |
|
a = np.dot(z, self.weight[i]) + self.bias[i] |
|
z = sigmoid(a) |
|
an = np.dot(z, self.weight[self.numNeuronLayers - 1]) + self.bias[self.numNeuronLayers - 1] |
|
y = softmax(an) |
|
return y |
|
|
|
def gradient(self, x, t): |
|
z = [] |
|
a = [] |
|
z.append(x) |
|
|
|
for i in range(self.numNeuronLayers): |
|
a.append(np.dot(z[i], self.weight[i]) + self.bias[i]) |
|
z.append(sigmoid(a[i])) |
|
y = softmax(a[self.numNeuronLayers - 1]) |
|
num = x.shape[0] |
|
dy = (y - t) / num |
|
dz = [] |
|
da = [] |
|
dz.append(dy) |
|
for i in range(self.numNeuronLayers - 1): |
|
da.append(np.dot(dz[i], self.weight[self.numNeuronLayers - i - 1].T)) |
|
dz.append(sigmoid_grad(a[self.numNeuronLayers - i - 2]) * da[i]) |
|
|
|
for i in range(self.numNeuronLayers): |
|
self.weight[i] -= self.learningRate * np.dot(z[i].T, dz[self.numNeuronLayers - i - 1]) |
|
self.bias[i] -= self.learningRate * np.sum(dz[self.numNeuronLayers - i - 1], axis=0) |
|
|
|
def loss(self, x, t): |
|
y = self.predict(x) |
|
t = t.argmax(axis=1) |
|
num = y.shape[0] |
|
s = y[np.arange(num), t] |
|
return -np.sum(np.log(s)) / num |
|
|
|
def accuracy(self, x, t): |
|
y = self.predict(x) |
|
p = np.argmax(y, axis=1) |
|
q = np.argmax(t, axis=1) |
|
acc = np.sum(p == q) / len(y) |
|
return acc |
|
|
|
|
|
def kNN(x_train, x_test, t_train, k): |
|
px = list() |
|
for i in range(len(x_test)): |
|
px.append([]) |
|
for j in range(10): |
|
px[i].append(0) |
|
for i in range(len(x_test)): |
|
dis = getODistance(x_test[i], x_train) |
|
index = np.argsort(dis) |
|
count = list() |
|
r = np.sort(dis)[k - 1] |
|
for j in range(len(t_train[0])): |
|
count.append(0) |
|
for j in range(k): |
|
for w in range(10): |
|
if t_train[index[j]][w] == 1: |
|
count[w] = count[w] + 1 |
|
for j in range(10): |
|
px[i][j] = count[j] |
|
return px |
|
|
|
|
|
def getODistance(sample, train): |
|
a = np.tile(sample, [1000, 1]) |
|
a = a - train |
|
a = np.square(a) |
|
a = a.sum(axis=1) |
|
dis = np.sqrt(a) |
|
dis = dis.T |
|
dis = dis.tolist() |
|
return dis[0] |
|
|
|
|
|
def runNetwork(): |
|
numNeuronLayers = 3 |
|
numNeurons_perLayer = [3072, 50, 20, 10] |
|
learningRate = 0.05 |
|
epoch = 50000 |
|
batch_size = 100 |
|
train_size = x_train.shape[0] |
|
|
|
net = neuralNetwork(numNeuronLayers, numNeurons_perLayer, learningRate) |
|
for i in range(epoch): |
|
batch_mask = np.random.choice(train_size, batch_size) |
|
x_batch = x_train[batch_mask] |
|
t_batch = t_train[batch_mask] |
|
net.gradient(x_batch, t_batch) |
|
y = net.predict(x_test[0:1000, 0:3072]) |
|
p = np.argmax(y, axis=1) |
|
q = np.argmax(t_test[0:1000, 0:3072], axis=1) |
|
acc = np.sum(p == q) / len(y) |
|
print("神经网络正确率为:", acc) |
|
return p |
|
|
|
|
|
def runKnn(x_train, x_test): |
|
x_train = np.mat(x_train) |
|
x_test = np.mat(x_test) |
|
px = kNN(x_train[0:1000, 0:3072], x_test[0:1000, 0:3072], t_train[0:1000, 0:10], 7) |
|
p = np.argmax(px, axis=1) |
|
q = np.argmax(t_test[0:1000, 0:3072], axis=1) |
|
acc = np.sum(p == q) / 1000 |
|
print("knn正确率为:", acc) |
|
return p |
|
|
|
|
|
from sklearn import svm |
|
|
|
|
|
def runSvm(): |
|
clf = svm.SVC(probability=True) |
|
t = np.argmax(t_train[0:1000, 0:3072], axis=1) |
|
clf.fit(x_train[0:1000, 0:3072], t) |
|
p = clf.predict(x_test[0:1000, 0:3072]) |
|
q = np.argmax(t_test[0:1000, 0:3072], axis=1) |
|
acc = np.sum(p == q) / 1000 |
|
print("svm正确率为:", acc) |
|
return p |
|
|
|
|
|
data_dir = 'cifar-10-batches-py' |
|
x_train, t_train, x_test, t_test = load_data(data_dir) |
|
encoder = OneHotEncoder(sparse=False) |
|
one_format = [[0], [1], [2], [3], [4], [5], [6], [7], [8], [9]] |
|
encoder.fit(one_format) |
|
t_train = t_train.reshape(-1, 1) |
|
t_train = encoder.transform(t_train) |
|
t_test = t_test.reshape(-1, 1) |
|
t_test = encoder.transform(t_test) |
|
|
|
p1 = runNetwork() |
|
p2 = runSvm() |
|
p3 = runKnn(x_train, x_test) |
|
|
|
p1 = p1.reshape(-1, 1) |
|
p1 = encoder.transform(p1) |
|
p2 = p2.reshape(-1, 1) |
|
p2 = encoder.transform(p2) |
|
p3 = p3.reshape(-1, 1) |
|
p3 = encoder.transform(p3) |
|
|
|
vote = p1+p2+p3 |
|
p = np.argmax(vote, axis=1) |
|
q = np.argmax(t_test[0:1000, 0:3072], axis=1) |
|
acc = np.sum(p == q) / 1000 |
|
print("最终正确率为", acc) |
|
|
|
|