深度学习实验Lab1——张量基础操作、神经元模型

小结:
这次实验课给我的感受还是很深的,对于很多张量的操作,还有对于图像通道的深层应用都不熟悉。并且通过亲自编写函数,实现了很多函数功能,对于这些函数体会更加深刻
对于神经元模型的编写,本次实验的内容是需要通过交叉熵损失函数构建一个对率回归模型。但是需要注意的是torch里的交叉熵损失函数内封装了softmax + log + NLLLoss三个函数,因此这里单独手写交叉熵损失函数。

深度学习实验一:PyTorch Tensor

本次实验中,练习PyTorch Tensor的操作。请按以下要求完成编程:

name = 'yyh'#填写你的姓名
sid = 'B02014152'#填写你的学号

print('姓名:%s, 学号:%s'%(name, sid))
import torch
import numpy as np
import matplotlib.pyplot as plt

1. 创建和操作Tensor

在这一部分,你将要用tensor创建张量,并对张量做一些处理。
请按照以下要求编写代码:

#创建一个shape=(5,10)的随机张量,张量的元素满足标准高斯分布

X = torch.randn((5,10))

print(X)
#在下面输出X的形状、维度

######B02014152杨宇海######
print("X的形状", X.shape)
print("X的第一维维度", X.shape[0])
print("X的第二维维度", X.shape[1])

假设 X X X的每一列表示一个特征向量 X ( i ) X^{(i)} X(i),请在下面对X做标准化处理,即:

X j ( i ) = X j ( i ) − μ j σ j + ε X_{j}^{(i)}=\frac{X_{j}^{(i)}-\mu_{j}}{\sigma_{j} + \varepsilon} Xj(i)=σj+εXj(i)μj

其中, μ \mu μ是样本均值向量, σ \sigma σ是样本的标准差向量, ε \varepsilon ε是一个很小的正数,可以取为 1 e − 7 1e-7 1e7

#请在下面编写代码将X做标准化,得到张量Y

###B02014152杨宇海###
import math
def standardization(X):
    # 将二维张量,按列为样本,对样本进行归一化
    row = X.shape[0]
    col = X.shape[1]
    # 计算mu
    u = torch.zeros((row,1))
    for i in range(row):
        for j in range(col):
            u[i, 0] += X[i, j]
    u /= col
    # 计算sigma
    sigma = torch.zeros((row,1))
    for i in range(row):
        for j in range(col):
            sigma[i,0] += (X[i, j] - u[i, 0])**2 # (xi-xu)^2
        sigma[i,0] = math.sqrt(sigma[i,0]/col) # sqrt(x/n)
    sigma += 1e-7
    # print(u)
    # print(sigma)
    return (X-u)/sigma

Y = standardization(X) 
print(Y)
#在下面编写代码输出Y的均值和每个维度的最大、最小值

###B02014152杨宇海###
miu = torch.mean(Y, dim=1, keepdim=True)#计算Y的行均值,请用一行代码实现
# print(miu)

maxV = torch.max(Y, dim=1, keepdim=True)#计算Y的行最大值,请用一行代码实现
# print(maxV[0])
    
minV = torch.max(Y, dim=1, keepdim=True)#计算Y的行最小值,请用一行代码实现
# print(minV[0])

#下面的代码构造了一个3维张量a
a = torch.tensor([[[1,2,3],[4,5,6]],[[-3,-4,-5],[-6,-7,-8]],[[7,8,9],[10,11,12]]])
print(a)
#请在下面编写代码,对a进行操作,得到如下的张量:
'''tensor([[[ 1, -3,  7],
         [ 4, -6, 10]],

        [[ 2, -4,  8],
         [ 5, -7, 11]],

        [[ 3, -5,  9],
         [ 6, -8, 12]]])'''

b = a.permute(2,1,0)#请用一行代码实现
print(b)
#下面的代码读入一张彩色图像
import cv2 as cv
im = cv.imread('car0.jpg')

print(im.shape)
#opencv读入的图像是一个numpy ndarray
type(im)
#显示彩色图像,注意显示的颜色是错误的,
#原因是opencv读入的图像三个颜色通道是B,G,R,不是R,G,B。而matplotlib绘制图像的时候,当作R,G,B绘制。

plt.figure(figsize = (10,6))
plt.imshow(im)
plt.axis('off')
plt.show()
#下面的代码把im在第2个维度上翻转,把BGR变换为RGB,结果可以正常显示
im1 = np.flip(im,axis = 2)
plt.figure(figsize = (10,6))
plt.imshow(im1)
plt.axis('off')
plt.show()
#在下面编写代码,把im转换为一个张量
im_tensor = torch.from_numpy(im)#请用一行代码实现

im_tensor.shape
im2 = im_tensor.numpy()
plt.imshow(im2)
plt.axis('off')
plt.show()
#在下面用张量操作,把三个通道的顺序从BGR转换为RGB
im_t1 = torch.flip(im_tensor[:,:], [2])#请用一行代码实现,提示:torch.flip
# [2]代表将第二维的BGR 倒转为 RGB 

im_t1.shape
plt.imshow(im_t1)
im3 = im_t1.numpy()
plt.imshow(im3)
plt.axis('off')
plt.show()
#请在下面编写代码,从im_t1中分离出三个通道:
R,G,B =  torch.split(im_t1, [1,1,1],dim=2)#请用一行代码实现,提示torch.dsplit(这里由于torch版本没有dsplit,改为使用split)
print(R.shape)
#请在下面编写代码,把R,G,B三个张量水平拼成一个张量

RGB =  torch.hstack((R,G,B))#请用一行代码实现,提示torch.hstack

print(RGB.shape)
plt.figure(figsize=(18,3))
plt.imshow(RGB,cmap = 'gray')
plt.axis('off')
plt.show()
#在下面编写代码将im_t1中的彩色图像转换为灰度图
#转换公式为:GRAY = 0.3*r+0.59*G+0.11*B
#请使用广播实现

weights = torch.ones((600, 1200, 3))#构造一个权值张量,表示R,G,B通道的权重
weights[:,:,0] = 0.3
weights[:,:,1] = 0.59
weights[:,:,2] = 0.11

temp = im_t1 * weights
gray = temp[:,:,0]+temp[:,:,1]+temp[:,:,2]#用权值张量把im_t1转换为灰度图,可能需要多行代码实现
# gray = gray.unsqueeze(2)

gray.shape
plt.imshow(gray)
plt.imshow(gray.numpy(),cmap = 'gray')
plt.axis('off')
plt.show()
#im_t1的数据元素类型是unit8
im_t1.dtype # torch.Size([600, 1200, 3])
#请把im_t1的数据类型转换为torch.float32,并归一化到[0,1]区间

im_t2 =  (im_t1.to(torch.float32) - im_t1.to(torch.float32).min())/(im_t1.to(torch.float32).max()-im_t1.to(torch.float32).min())#请用一行代码实现,提示Tensor.to



print(im_t2[0,0,0])
#向im_t2中添加随机高斯噪声
#噪声均值为0,标准差为std
std = 0.02

import random
im_t3 =  im_t2 + random.gauss(0, std)#请用一行代码是新啊
print(im_t3[0,0,0])

print(im_t3.max())
#把im_t3的值截取到[0,1]区间
im_t3 =  torch.clamp(im_t3, 0, 1)#请用一行代码实现,提示torch.clamp
# print(im_t3.max())
plt.imshow(im_t3.numpy())
plt.axis('off')
plt.show()

2. 用Tensor编写神经元模型

一个神经元表示以下函数: h ( x ) = f ( W T x + b ) h(x)=f(W^{T}x+b) h(x)=f(WTx+b).其中 f f f是非线性响应函数。

请用Tensor编写一个对率回归模型,并用梯度下降法训练该模型。

#定义sigmoid函数:
def sigmoid(z):
    rho = 1/(1+torch.exp(-z))#请用一行代码实现,提示torch.exp
    return rho
t = torch.tensor([-5,-1,0,10],dtype = torch.float32)
print(sigmoid(t))
#定义一个表示logistic regression的函数:
def logReg(X,W,b):
    #计算净响应
    z =  W.permute(1,0)@X+b#请用一行代码实现,提示@
    rho = sigmoid(z)
    # for i in range(len(rho[0])):
    #     if rho[0][i]>=0.5:
    #         rho[0][i] = 1
    #     else:
    #         rho[0][i] = 0
    return rho
W = torch.zeros((2,1))
b = 0
X = torch.randn((2,10))
print(logReg(X,W,b))
# 生成随机样本:
X0 = torch.randn((2,100))*0.7 + torch.ones((2,1),dtype = torch.float32)
X1 = torch.randn((2,100))*0.7 - torch.ones((2,1),dtype = torch.float32)
X = torch.hstack((X0,X1))
Y = torch.hstack((torch.zeros((1,100)), torch.ones((1,100))))
x0 = X0.numpy()
x1 = X1.numpy()
plt.plot(x0[0],x0[1],'bo')
plt.plot(x1[0],x1[1],'r*')
plt.axis('equal')
plt.show()
#在下面编写函数,训练一个对率回归模型

def trainLogReg(X,Y):
    #初始化W,b:
    W = torch.zeros((X.shape[0],1))
    b = 0
    
    #学习速率:
    alpha = 0.5
    
    epsilon = 1e-5
    
    #初始损失
    loss0 = np.inf
    iter = 1
    while(True):
        #计算预测值rho
        rho = logReg(X,W,Y)#请用一行代码实现

        #在下面计算log-loss
        print(rho.size(), Y.size())
        loss = (-torch.log(rho[Y==1]).sum()-torch.log(1-rho[Y==0]).sum())/Y.shape[1]
        # print((-torch.log(rho*Y).sum()-torch.log(1+rho*(Y-1)).sum())/Y.shape[1])
        loss = loss.item()
        # print(loss)
        
        print('iter = %d, loss = %.5f'%(iter, loss))
        iter = iter + 1
        
        if(np.abs(loss - loss0)<epsilon):
            break
        loss0 = loss
        
        #计算误差err
        err =  rho-Y#请用一行代码实现
        
        #计算梯度:
        dW = ((err*X).sum(axis=1)/Y.shape[1]).unsqueeze(1)#请用一行代码实现
        db = err.sum()/Y.shape[1]#请用一行代码实现
        # print(dW)
        #梯度下降
        # print(W)
        W = W - alpha * dW
        # print(W)
        # print(b)
        b = b - alpha * db
        # print(b)
        
    return W,b
W,b = trainLogReg(X,Y)
print('W = ', W)
print('b = ', b)
#绘制分界面:

W0 = W.numpy()
b0 = b.item()

maxx = torch.max(X,dim = 1).values[0].item()
minx = torch.min(X,dim = 1).values[0].item()
print(maxx)
print(minx)
x = np.array([minx,maxx])
y = -(W0[0] * x + b0) / W0[1]
x0 = X0.numpy()
x1 = X1.numpy()
plt.plot(x0[0],x0[1],'bo')
plt.plot(x1[0],x1[1],'r*')
plt.plot(x,y,'k-')
plt.axis('equal')
plt.show()

你可能感兴趣的:(深度学习实验,深度学习,python,numpy)