前言
本文为9月28日计算机视觉基础学习笔记——卷积神经网络,分为三个章节:
- Week 5 homework——K++ means;
- 图像滤波;
- CNN。
一、Week 5 homework——K++ means
# coding:utf-8
# KMeans
# step1:随机设定初始聚类中心
# step2:将距离某个聚类中心距离近的样本点归类到该聚类中心,将样本全部归类完毕后得到多个簇
# step3:计算每个簇的均值作为新的聚类中心
# step4:重复第二步和第三步直至聚类中心不再发生变化
# KMeans++
# step1:首先从所有样本中随机选定第一个聚类中心
# step2:记录所有样本到与其最近的聚类中心的距离
# step3:所有非聚类中心样本点被选取作为下一个聚类中心的概率与step2中的距离大小成正比,也就是说距离越远的样本点越有可能成为下一个聚类中心
# step4:重复step2和step3直至选出多个聚类中心
import numpy as np
import sklearn.datasets
from mnist import MNIST
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import torch
def generate_data():
# 本函数生成0-9,10个数字的图片矩阵
image_data = []
num_0 = torch.tensor(
[[0, 0, 1, 1, 0, 0],
[0, 1, 0, 0, 1, 0],
[0, 1, 0, 0, 1, 0],
[0, 1, 0, 0, 1, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0]])
image_data.append(num_0)
num_1 = torch.tensor(
[[0, 0, 0, 1, 0, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0]])
image_data.append(num_1)
num_2 = torch.tensor(
[[0, 0, 1, 1, 0, 0],
[0, 1, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0],
[0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 0, 0]])
image_data.append(num_2)
num_3 = torch.tensor(
[[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0]])
image_data.append(num_3)
num_4 = torch.tensor(
[
[0, 0, 0, 0, 1, 0],
[0, 0, 0, 1, 1, 0],
[0, 0, 1, 0, 1, 0],
[0, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0]])
image_data.append(num_4)
num_5 = torch.tensor(
[
[0, 1, 1, 1, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 1, 0],
[0, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0]])
image_data.append(num_5)
num_6 = torch.tensor(
[[0, 0, 1, 1, 0, 0],
[0, 1, 0, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[0, 1, 0, 0, 1, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0]])
image_data.append(num_6)
num_7 = torch.tensor(
[
[0, 1, 1, 1, 1, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0]])
image_data.append(num_7)
num_8 = torch.tensor(
[[0, 0, 1, 1, 0, 0],
[0, 1, 0, 0, 1, 0],
[0, 0, 1, 1, 0, 0],
[0, 1, 0, 0, 1, 0],
[0, 0, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0]])
image_data.append(num_8)
num_9 = torch.tensor(
[[0, 0, 1, 1, 1, 0],
[0, 1, 0, 0, 1, 0],
[0, 0, 1, 1, 1, 0],
[0, 1, 0, 0, 1, 0],
[0, 0, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0]])
image_data.append(num_9)
image_label = [0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]
return image_data, image_label
class KMcluster():
def __init__(self, X, y, n_clusters=3, initialize="random", max_iters=10):
self.X = X
self.y = y
self.n_clusters = n_clusters
self.initialize = initialize
self.max_iters = max_iters
# 随机初始化中心点
def init_random(self):
# min, max = np.min(self.X)-1, np.max(self.X)+1
# n_features = self.X.shape[1]
# centroids = min + (max-min) * np.random.random((self.n_clusters, n_features))
n_samples, n_features = self.X.shape
centroids = self.X[np.random.choice(n_samples, self.n_clusters)]
return centroids
# KMeans++ 初始化中心点
def init_kmeans_plusplus(self):
n_samples, n_features = self.X.shape
# step 1: 随机选取第一个中心点
centroids = self.X[np.random.choice(n_samples, 1)]
# 计算其余的中心点
for k in range(0, self.n_clusters-1):
distances = np.zeros((n_samples, k+1))
# step 2: 计算每个样本到每一个聚类中心的欧式距离
for i in range(len(centroids)):
distances[:, i] = np.sqrt(np.sum(np.square(self.X - centroids[i]), axis=1))
# step 3: 计算每个样本与最近聚类中心(指已选择的聚类中心)的距离D(x)
# np.argmin
dist = np.min(distances, axis=1)
# step 4: 再取一个随机值,用权重的方式来取计算下一个“种子点”。具体实现是,先取一个能落在Sum(D(x))中的随机值Random,
# 然后用Random -= D(x),直到其<=0,此时的点就是下一个“种子点”。
total = np.sum(dist) * np.random.rand()
for j in range(n_samples):
total -= dist[j]
if total > 0:
continue
centroids = np.r_[centroids, self.X[j].reshape(-1, 2)]
break
# print(centroids)
return centroids
def assignment(self, centroids):
n_samples = self.X.shape[0]
distances = np.zeros((n_samples, self.n_clusters))
for i in range(self.n_clusters):
distances[:, i] = np.sum(np.square(self.X - centroids[i]), axis=1)
return np.argmin(distances, axis=1)
def update_center(self, flag, centroids):
new_centroids = np.zeros_like(centroids)
for i in range(self.n_clusters):
new_centroids[i] = np.mean(self.X[flag == i], axis=0)
return new_centroids
def train(self):
# step 1: generate center
if self.initialize == "kmeans++":
centroids = self.init_kmeans_plusplus()
else:
centroids = self.init_random()
colmap = [i for i in range(self.n_clusters)]
for i in range(self.max_iters):
# step 2: assign centroid for each source data
flag = self.assignment(centroids)
#plt.scatter(self.X[:, 0], self.X[:, 1], c=flag, marker=".", alpha=0.5)
#plt.scatter(centroids[:, 0], centroids[:, 1], c=colmap, marker="o", linewidths=6)
#plt.show()
# step 3: re-caculate center
new_centroids = self.update_center(flag, centroids)
# 终止条件,如果重新计算的中心点与上一次的重复,则退出训练
if (new_centroids == centroids).all():
break
else:
centroids = new_centroids
print("iters: ", i, ", center point: ", centroids)
if __name__ == "__main__":
'''
# 生成数据集: X[2000, 2], y[2000], 4 clusters
X, y = sklearn.datasets.make_blobs(n_samples=2000,
n_features=2,
centers=4,
random_state=40,
cluster_std=(2.5, 2, 2.5, 2))
km = KMcluster(X, y, n_clusters=4, initialize="random", max_iters=50)
# km = KMcluster(X, y, n_clusters=4, initialize="kmeans++", max_iters=50)
km.train()
'''
# hct66 dataset
image_data, image_label = generate_data() # generate source data
image_label = np.array(image_label)
col, row = image_data[0].shape
image_values = np.zeros((len(image_label), col * row))
import pdb
pdb.set_trace()
for idx, image_value in enumerate(image_data):
image_values[idx, :] = image_value.flatten()
# Normalize the data
image_values_norm = StandardScaler().fit_transform(image_values)
import pdb
pdb.set_trace()
# PCA 降维
pca = PCA(n_components=6)
image_values_pca = pca.fit(image_values_norm).transform(image_values_norm)
print(image_values_pca.shape)
#km = KMcluster(image_values_pca, image_label, n_clusters=3, initialize="random", max_iters=10)
km = KMcluster(image_values_pca, image_label, n_clusters=3, initialize="keams++", max_iters=10)
km.train()
二、图像滤波
- 正弦曲线:
y = A s i n ( w x + b ) y = A\ sin(wx + b) y=A sin(wx+b)
import cv2
import numpy as np
import os
img = cv2.imread("../week1/lena.jpg")
# # 图像滤波/卷积
kernel = np.ones((3,3),np.float32)/8
kernel=-kernel
kernel[0,:]=[-1,0,1]
kernel[1,:]=[-1,0,1]
kernel[2,:]=[-1,0,1]
print(kernel)
#plt.imshow(img)
#dst=cv.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]);当ddepth=-1> 时,表示输出图像与原图像有相同的深度。
print(img.shape)
result = cv2.filter2D(img,-1,kernel)
result.shape
print(result[0,0])
#plt.imshow(result*255)
result = cv2.filter2D(result,-1,kernel)
cv2.imwrite("filter2d_result.png",result)
os.system("open filter2d_result.png")
os.system("open ../week1/lena.jpg")
三、CNN
import torch
from torch import nn
import os
# 生成tensor
x = torch.tensor([[1.,2.,3.,7.],[6,3,4,2]])
# 也可以从图片中读取
print(x)
convolution=nn.Conv2d(1,1,kernel_size = 2,stride=2,padding=0)
#print(convolution(x))
# 查看卷积类都有哪些成员函数与成员变量
dir(convolution)
# 对x 进行维度变换
x1=x.view(1,1,2,4)
#with torch.no_grad()
print(convolution(x1))
#改变卷积核的取值
convolution.weight.data=torch.tensor([[[[1.,-1.],[1.,-1.]]]])
#改变偏移量得取值
convolution.bias.data =torch.tensor([0.0])
print(convolution(x1))
# 读取mnist数据
import sys
sys.path.append("../week4")
from mnist import MNIST
mndata = MNIST('../week4/mnist/python-mnist/data/')
image_data_all, image_label_all = mndata.load_training()
image_data=image_data_all[0:100]
image_label=image_label_all[0:100]
x = torch.tensor(image_data[0])
#np.array(image_data[3]).reshape((28,28)).astype('uint8')
img=x.view(1,1,28,28)
img_show=x.view(28,28)
import cv2
cv2.imwrite("img_show.png",img_show.numpy().astype("uint8"))
os.system("open img_show.png")
img = img.float()
feature= convolution(img)
feature_show =feature.view(15,15)
cv2.imwrite("feature_show.png",feature_show.detach().numpy().astype("uint8"))
os.system("open feature_show.png")
print(image_label)
def show_image(img):
cv2.imwrite("tmp.png",img.detach().numpy().astype("uint8"))
os.system("open tmp.png")
show_image(feature_show)
show_image(img_show)
show_image((convolution(torch.tensor(image_data[0]).view(1,1,28,28).float())).view(15,15))
conv2=nn.Conv2d(1,1,kernel_size = 2,stride=2,padding=1)
show_image((conv2(torch.tensor(image_data[0]).view(1,1,28,28).float())).view(15,15))
print("end")