zack

zack 查看完整档案

广州编辑  |  填写毕业院校广州大学黄埔研究院  |  硕士 编辑 yonggie.github.io 编辑
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

zack 提出了问题 · 4月5日

请问下torch loss function输入的维度,如何去扩展高维?

前提:

b_xent=torch.nn.CrossEntropyLoss()

不报错案例

没问题1

a=torch.tensor([[0.02,0.3],[0.3,0.3],[0.3,0.3]])
b=torch.tensor([0,1,1])
b_xent(a,b)

Out[3]: tensor(0.7680)

报错案例

若直接扩展维度,报错

a=a.unsqueeze(0)
b=b.unsqueeze(0)
a.shape  # Out[20]: torch.Size([1, 3, 2])
b.shape  # Out[21]: torch.Size([1, 3])
b_xent(a,b)

维度出错2

a=torch.randn((1,273,512))
b=torch.randn((1,273))
b_xent(a,b)

报错内容:

Traceback (most recent call last):
  File "D:\lib\site-packages\IPython\core\interactiveshell.py", line 3418, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-1-b7d4d1dd28a0>", line 3, in <module>
    b_xent(a,b)
  File "D:\lib\site-packages\torch\nn\modules\module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "D:\lib\site-packages\torch\nn\modules\loss.py", line 961, in forward
    return F.cross_entropy(input, target, weight=self.weight,
  File "D:\lib\site-packages\torch\nn\functional.py", line 2468, in cross_entropy
    return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
  File "D:\lib\site-packages\torch\nn\functional.py", line 2273, in nll_loss
    raise ValueError('Expected target size {}, got {}'.format(
ValueError: Expected target size (1, 512), got torch.Size([1, 273])

那么如何在input和label都升高维度,并且使用CELoss呢?

关注 2 回答 1

zack 提出了问题 · 4月5日

请问下torch loss function输入的维度,如何去扩展高维?

前提:

b_xent=torch.nn.CrossEntropyLoss()

不报错案例

没问题1

a=torch.tensor([[0.02,0.3],[0.3,0.3],[0.3,0.3]])
b=torch.tensor([0,1,1])
b_xent(a,b)

Out[3]: tensor(0.7680)

报错案例

若直接扩展维度,报错

a=a.unsqueeze(0)
b=b.unsqueeze(0)
a.shape  # Out[20]: torch.Size([1, 3, 2])
b.shape  # Out[21]: torch.Size([1, 3])
b_xent(a,b)

维度出错2

a=torch.randn((1,273,512))
b=torch.randn((1,273))
b_xent(a,b)

报错内容:

Traceback (most recent call last):
  File "D:\lib\site-packages\IPython\core\interactiveshell.py", line 3418, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)
  File "<ipython-input-1-b7d4d1dd28a0>", line 3, in <module>
    b_xent(a,b)
  File "D:\lib\site-packages\torch\nn\modules\module.py", line 727, in _call_impl
    result = self.forward(*input, **kwargs)
  File "D:\lib\site-packages\torch\nn\modules\loss.py", line 961, in forward
    return F.cross_entropy(input, target, weight=self.weight,
  File "D:\lib\site-packages\torch\nn\functional.py", line 2468, in cross_entropy
    return nll_loss(log_softmax(input, 1), target, weight, None, ignore_index, None, reduction)
  File "D:\lib\site-packages\torch\nn\functional.py", line 2273, in nll_loss
    raise ValueError('Expected target size {}, got {}'.format(
ValueError: Expected target size (1, 512), got torch.Size([1, 273])

那么如何在input和label都升高维度,并且使用CELoss呢?

关注 2 回答 1

zack 发布了文章 · 2020-11-04

python opencv 自适应大小中央显示图片或者视频

先给代码

中央显示图片

三个工具函数,直接后面有三行代码的示例。

import cv2
import tkinter as tk



def GetScreenCenter():
    root = tk.Tk()
    return root.winfo_screenwidth()//2,root.winfo_screenheight()//2

def AdaptSize(img):
    # 视频、图片过大直接1/2
    center_x, center_y = GetScreenCenter()
    img_h, img_w, _ = img.shape
    if img_h > center_y * 2 or img_w > center_x * 2:
        img = cv2.resize(img, (img_w // 2, img_h // 2))
    return img

def CentralShow(win_name,video):
    ret,img=video.read()
    center_x, center_y = GetScreenCenter()
    img=AdaptSize(img)
    img_h,img_w,_=img.shape
    t_x, t_y = (center_x - img_w // 2), (center_y - img_h // 2)
    cv2.imshow(win_name, img)
    cv2.moveWindow(win_name, t_x, t_y)
    cv2.waitKey(0)

# example:
win_name='centered image'
img=cv2.imread('english.jpg')
CentralShow(win_name,img)

中央显示视频

视频其实是多个图片不断循环,只需多次读取视频图片即可

import cv2
import tkinter as tk

def GetScreenCenter():
    root = tk.Tk()
    return root.winfo_screenwidth()//2,root.winfo_screenheight()//2

def AdaptSize(img):
    # 视频、图片过大直接1/2
    center_x, center_y = GetScreenCenter()
    img_h, img_w, _ = img.shape
    if img_h > center_y * 2 or img_w > center_x * 2:
        img = cv2.resize(img, (img_w // 2, img_h // 2))
    return img

def CentralShow(win_name,video):
    ret,img=video.read()
    center_x, center_y = GetScreenCenter()
    img=AdaptSize(img)
    img_h,img_w,_=img.shape
    t_x, t_y = (center_x - img_w // 2), (center_y - img_h // 2)
    cv2.imshow(win_name, img)
    cv2.moveWindow(win_name, t_x, t_y)

def ShowVideo(video):
    while True:
        ret, imgsrc = video.read()
        if imgsrc is None:
            break
        imgsrc = AdaptSize(imgsrc)
        cv2.imshow(win_name, imgsrc)

        if cv2.waitKey(20) & 0xFF == ord('q'):
            break

    video.release()
    cv2.destroyAllWindows()

# eg:
win_name='centered video'
video = cv2.VideoCapture('1604400296582.mp4')

# 先第一次确定显示的位置
CentralShow(win_name,video)
# 整个视频放映(无声放映)
ShowVideo(video)

代码一些解释

实现思路

  1. 获取整个屏幕width, height,找到中心点
  2. 得到图片的长宽,然后通过中心点,计算显示图片窗口的左上角点的位置。
  3. 显示图片

利用opencv的窗口的特点

我使用moveWindow这个函数,意思是把窗口移动到其他地方。
opencv的窗口显示有个特点,只要上一次move到这个地方显示,下一次也会在这个地方显示,没有个指定显示地方的函数。
所以我的方法是,先在随便地方显示,然后move到指定地方。然后之后的都会在那个地方显示了。

查看原文

赞 0 收藏 0 评论 0

zack 关注了用户 · 2020-08-19

大舒 @qiukeren

define TRUE FALSE

Exception up = new Exception("Something is really wrong."); throw up;

如果 我给人点赞,有些是我支持他的观点,有些仅仅是我不希望他被人扣得太惨。

拒绝回答一切过于小白的问题。

关注 671

zack 发布了文章 · 2020-07-08

pytorch分别用MLP和RNN拟合sinx

0

理论上带有一个非线性函数的网络能够拟合任意函数。那显然MLP和RNN是科研拟合sinx的。
开头先把结果给展示出来,然后是代码,最后是我的过程。懒得看的直接看前半部分行了,过程给有兴趣的人看看。

先上结果图

注:每次训练torch初始化有不同,所以结果有出入。
在这里插入图片描述

代码

乍一看挺多的,实际上简单得一批。只不过是定义了两个网络,训练了两次,展示图片的重复代码而已。具体代码已经注释。

import torch
import math
import matplotlib.pyplot as plt




class MLP(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.layer1=torch.nn.Linear(1,16)
        self.layer2=torch.nn.Linear(16,16)
        self.layer3=torch.nn.Linear(16,1)

    def forward(self,x):
        x=self.layer1(x)
        x=torch.nn.functional.relu(x)

        x=self.layer2(x)
        x=torch.nn.functional.relu(x)

        x=self.layer3(x)

        return x

# rnn takes 3d input while mlp only takes 2d input
class RecNN(torch.nn.Module):
    def __init__(self):
        super().__init__()
        self.rnn=torch.nn.LSTM(input_size=1,hidden_size=2,num_layers=1,batch_first=True)
        #至于这个线性层为什么是2维度接收,要看最后网络输出的维度是否匹配label的维度
        self.linear=torch.nn.Linear(2,1)
        
    def forward(self,x):
        # print("x shape: {}".format(x.shape))
        # x [batch_size, seq_len, input_size]
        output,hn=self.rnn(x)
        # print("output shape: {}".format(output.shape))
        # out [seq_len, batch_size, hidden_size]
        x=output.reshape(-1,2)
    
        # print("after change shape: {}".format(x.shape))
        x=self.linear(x)

        # print("after linear shape: {}".format(x.shape))

        return x

def PlotCurve(mlp, rnn, input_x, x):
    # input_x 是输入网络的x。
    # sin_x 是列表,x的取值,一维数据、
    # 虽然他们的内容(不是维度)是一样的。可以print shape看一下。
    mlp_eval = mlp.eval()
    rnn_eval = rnn.eval()
    mlp_y = mlp_eval(input_x)
    rnn_y = rnn_eval(input_x.unsqueeze(0))

    plt.figure(figsize=(6, 8))

    plt.subplot(211)
    plt.plot([i + 1 for i in range(EPOCH)], mlp_loss, label='MLP')
    plt.plot([i + 1 for i in range(EPOCH)], rnn_loss, label='RNN')
    plt.title('loss')
    plt.legend()

    plt.subplot(212)
    plt.plot(x, torch.sin(x), label="original", linewidth=3)
    plt.plot(x, [y[0] for y in mlp_y], label='MLP')
    plt.plot(x, [y[0] for y in rnn_y], label='RNN')
    plt.title('evaluation')
    plt.legend()

    plt.tight_layout()
    plt.show()

#常量都取出来,以便改动
EPOCH=1000
RNN_LR=0.01
MLP_LR=0.001
left,right=-10,10
PI=math.pi

if __name__ == '__main__':
    mlp=MLP()
    rnn=RecNN()

    # x,y 是普通sinx 的torch tensor
    x = torch.tensor([num * PI / 4 for num in range(left, right)])
    y = torch.sin(x)
    # input_x和labels是训练网络时候用的输入和标签。
    input_x=x.reshape(-1, 1)
    labels=y.reshape(-1,1)


    #训练mlp
    mlp_optimizer=torch.optim.Adam(mlp.parameters(), lr=MLP_LR)
    mlp_loss=[]
    for epoch in range(EPOCH):
        preds=mlp(input_x)
        loss=torch.nn.functional.mse_loss(preds,labels)

        mlp_optimizer.zero_grad()
        loss.backward()
        mlp_optimizer.step()
        mlp_loss.append(loss.item())

    #训练rnn
    rnn_optimizer=torch.optim.Adam(rnn.parameters(),lr=RNN_LR)
    rnn_loss=[]
    for epoch in range(EPOCH):
        preds=rnn(input_x.unsqueeze(0))
        # print(x.unsqueeze(0).shape)
        # print(preds.shape)
        # print(labels.shape)
        loss=torch.nn.functional.mse_loss(preds,labels)

        rnn_optimizer.zero_grad()
        loss.backward()
        rnn_optimizer.step()
        rnn_loss.append(loss.item())

    PlotCurve(mlp, rnn, input_x, x)

一些注意的点(过程)

  1. 有些人的代码是多加了dalaloader来做了数据集的loader,我个人认为没啥必要,这么简单的东西。当然加了loader或许更加符合习惯。
  2. 为什么数据只取了20个(从left到right只有sinx的20个数据)?我一开始是从-128附近取到了128附近,但是发现训练效果奇差无比,怀疑人生了都。这仅仅取了20个数据,都需要1000次训练,更大的数据集的时间代价可见一斑。
  3. RNN的lr是0.01,MLP的是0.001?这个也是根据loss的图来调节的,0.001在我这个rnn里并不适合,训练太慢了。而且为了和mlp的EPOCH保持一致,就换了0.01的学习率。但是为什么RNN比MLP下降的慢?这个有待进一步讨论(当然是因为我太菜了)。
  4. 关于loss function,为什么用mse loss?随便选的。我又换了l1_loss和其他的loss试了,效果差不多,毕竟这么简单的函数拟合,什么损失函数无所谓了。
  5. 论文指出,RNN系列网络比MLP拟合时间序列数据能力更强,为什么这次训练反而比MLP下降更慢?不仅如此,其实如果多次比较MLP和RNN的拟合效果,发现MLP效果更稳定更好一些,这又是为什么呢?有待进一步探讨。
查看原文

赞 0 收藏 0 评论 0

zack 发布了文章 · 2020-05-01

python AES加密&解密 torch模型

工具

用于AES的crypto,二进制字符转换十六进制字符用的binascii,以及torch。
python 在Windows下使用AES时要安装的是pycryptodome 模块 

pip install pycryptodome 

python 在Linux下使用AES时要安装的是pycrypto模块  

pip install pycrypto

关于AES

crypto里面的AES加密需要一个初始向量v,在下面的代码里变量叫做iv,需要是byte类型;还需要加密/解密用的key,在代码里的变量叫key。

代码

Net是我随便定义的一个网络。

  1. torch的save方法是用二进制数据保存的torch模型,我们也只能用二进制方法加密和解密。
  2. torch的load方法只能是load一个文件,并不能load一个对象,所以即便是你decrypte出来模型原文件,也只能先把它到文件里,然后在用torch load进来。
  3. 最后为了比较两个网络是否相同,我用了一个test_tensor去测试两个网络,得到相同的输出。注,比较前要先eval。具体见:这个博客
import torch
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
from Util import Net

# 如果byte_string不足16位的倍数就用空格补足为16位
def add_to_16(byte_string):
    if len(byte_string) % 16:
        add = 16 - (len(byte_string) % 16)
    else:
        add = 0
    byte_string = byte_string + (b'\0' * add)
    return byte_string


key = '9999999999999999'.encode('utf-8')
mode = AES.MODE_CBC
iv = b'qqqqqqqqqqqqqqqq'



# 加密函数
def Encrypt(byte_string):
    byte_string = add_to_16(byte_string)
    cryptos = AES.new(key, mode, iv)
    cipher_text = cryptos.encrypt(byte_string)
    # 因为AES加密后的字符串不一定是ascii字符集的,输出保存可能存在问题,所以这里转为16进制字符串
    return b2a_hex(cipher_text)


# 解密后,去掉补足的空格用strip() 去掉
def Decrypt(byte_string):
    cryptos = AES.new(key, mode, iv)
    plain_text = cryptos.decrypt(a2b_hex(byte_string))
    return plain_text.rstrip(b'\0')


if __name__ == '__main__':
    #测试向量
    test_tensor=torch.randn(1,14)
    net=Net()
    #全部保存
    torch.save(net,'model')
    
    #加密&写加密文件    
    with open('model','rb') as f1:
        encrypted=Encrypt(f1.read())
        with open('model-encrypted','wb') as f2:
            f2.write(encrypted)
    #解密 加密过的文件
    with open('model-decrypted','wb') as f:
        content=open('model-encrypted','rb').read()
        f.write(Decrypt(content))
    
    #load原本model
    net1=torch.load('./model')
    net1=net1.eval()
    #load解密后的model
    net2=torch.load('model-decrypted')
    net2=net2.eval()
    #测试结果
    print(net2(test_tensor), net1(test_tensor))
    exit(0)

查看原文

赞 0 收藏 0 评论 0

zack 提出了问题 · 2020-04-30

pytorch有没有一下子送进去data_set做test accuracy的简洁写法?

目前只会先把test_set放到data_loader里面,让batch-size等于len(test_set)。这样一次就可全放入。
但是也没有更简洁的写法?

    data_loader=torch.utils.data.DataLoader(test_set,batch_size=len(test_set))

    for x,labels in data_loader:
        preds=global_net(x)
        num=GetCorrectNum(preds,labels)
        

关注 1 回答 0

zack 回答了问题 · 2020-04-30

对于数据量不同的参与者,每个参与者训练相同网络下,比较其loss有意义吗,或者说,如何比较其loss值?

个人感觉,
loss的意义是表征训练是否正常,而test accuracy是表示模型在任务上表现好坏。
所以比较loss按照这个点来说的话,是没有意义的。

关注 1 回答 1

zack 提出了问题 · 2020-04-30

对于数据量不同的参与者,每个参与者训练相同网络下,比较其loss有意义吗,或者说,如何比较其loss值?

具体问题情境是这样的
网络结构就按照最简单的多层感知机假设好了。

a、b、c有不同的数据量1e2、1e4、1e6,他们各自有相同网络结构的模型(模型完全一样),用相同的loss_function,三个人都对自己的模型训练,训练过程中有loss值。

由于数据量不同,loss的值会不一样,数据量大的相对大一些。
如果只是单纯$\frac {loss}{数据量}$的话由于loss的值变动范围小,而数据量变动大,会使得数据量大的一方不管loss本身多大都会过小

如何去比较三者的loss值呢?(如果比较无意义,为什么无意义呢?)

关注 1 回答 1

zack 回答了问题 · 2020-04-16

解决请教下各位tkinter怎么用for循环显示图片?

这样写,多家一个img_list保留img对象。

image_size=(150,150)

img_list=[]
fm1=tk.Frame(window)
files=['candy.jpg','mosaic.jpg','rain-princess.jpg','udnie.jpg']
for file in files:
    img1 = Image.open(f'./images/style-images/{file}')
    img1 = img1.resize(image_size, Image.ANTIALIAS)
    img1 = ImageTk.PhotoImage(img1)
    img_list.append(img1)
    tk.Label(fm1, image=img1).pack(side=tk.RIGHT,padx=10)


fm1.pack()

关注 1 回答 1

认证与成就

  • 获得 4 次点赞
  • 获得 5 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 5 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2018-12-12
个人主页被 435 人浏览