深度学习神经网络项目常见小程序和帮助函数

一.前言

通常,我们的代码中需要一些小函数可以提高我们的代码阅读,这里做点笔记。

二.帮助函数

1. 显示时间
import time
import math

def asMinutes(s):
    m = math.floor(s / 60) # 地板取整
    s -= m * 60
    return '%dm %ds' % (m, s)


def timeSince(since, percent):
    now = time.time()
    s = now - since
    es = s / (percent)
    rs = es - s
    return '%s (- %s)' % (asMinutes(s), asMinutes(rs))

倾向第二个

'''
显示时间
input param: time.time()-start
'''
def time_since(s):  # compute time
    m = math.floor(s / 60)
    s -= m * 60
    h = math.floor(m / 60)
    m -= h * 60
    return '%dh %dm %ds' % (h, m, s)

当然最好用的还是封装:

显示当前时间
import datetime
nowTime = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
2.判断是不是中文
# 判断是不是中文的一个条件,在这之间就是中文
if (j >= u'\u4e00' and j <= u'\u9fa5')
3.使用单GPU和多GPU
'1.. 一共有几个cuda设备'
print(torch.cuda,device_count())
' 2. 查看所有的cuda设备信息'
device_nums = torch.cuda.device_count()
for i in range(device_nums):
    print(torch.device(i), torch.cuda.get_device_name(i))
' 3. 查看目前gpu是哪个设备'
print(torch.cuda.current_device())
' 4. 查看某个设备的信息'
print(torch.cuda.get_device_name(idx))
' 5. 查看cuda是否可用'
print(torch.cuda.is_available())
'6. 设定使用哪个cuda设备'
if torch.cuda.is_available():
    dev = "cuda:0" # 可以指定
else:
    dev = "cpu"
device = torch.device(dev)

'最后,最重要的使用gpu进行运算'
a = torch.zeros(2,3)
a = a.to(device)
'当是单个GPU时候,上面代码等价于下方'
a = a.cuda() # a可以是tensor也可以是net

关于显存的问题。这时候,把a.cuda()进行释放,比如a.cuda().cpu(),显存实际上没有释放,需要使用如下

# 释放显存
torch.cuda.empty_cache()
'释放后,nvidia-smi还是占用了大部分,其实变成了可以用,官方说明过'
4.数字字符串列表归一化为数字,方便运算对比
"这个函数进行数字化, 把  ['2%','1.5','0.02','4'] 变成 [0.02, 1.5, 0.02, 4.0]"
def num_list_processed(num_list):
    st = []
    for p in num_list:
        pos1 = re.search("\d+\(", p)
        pos2 = re.search("\)\d+", p)
        if pos1:
            st.append(eval(p[pos1.start(): pos1.end() - 1] + "+" + p[pos1.end() - 1:]))
        elif pos2:
            st.append(eval(p[:pos2.start() + 1] + "+" + p[pos2.start() + 1: pos2.end()]))
        elif p[-1] == "%":
            st.append(float(p[:-1]) / 100)
        else:
            st.append(eval(p))
    return st
def change_num(num):
    new_num = []
    for item in num:
        if '/' in item:
            new_str = item.split(')')[0]
            new_str = new_str.split('(')[1]
            a = float(new_str.split('/')[0])
            b = float(new_str.split('/')[1])
            value = a/b
            new_num.append(value)
        elif '%' in item:
            value = float(item[0:-1])/100
            new_num.append(value)
        else:
            new_num.append(float(item))
    return new_num
5. 数字排序并且返回下标
    "这个函数进行排序,把   [0.02, 1.5, 0.02, 4.0]  变成  1, 3, 1, 4] "
    '这种方式更好,可以知道哪些数字是相等的'
def num_order_processed(num_list):
    num_order = []
    num_array = np.asarray(num_list)
    for num in num_array:
        num_order.append(sum(num>num_array)+1)
    return num_order
def order_processer(nums):
    sorted_nums = sorted(enumerate(nums), key=lambda x: x[1])
    idx = [i[0] for i in sorted_nums]
    nums_ = [i[1] for i in sorted_nums]
    # 按大小排序下标(找不出相等函数);排序后的数字列表。
    return idx, nums_
6. 前缀、中缀、后缀表达式
6.1 前缀表达式转中缀表达式
class Stack(object):#用列表实现栈
    def __init__(self):	#实例化栈
        self.list = []
    def isEmpty(self):#判断栈空
        return self.list == []
    def push(self, item):#入栈
        self.list.append(item)
    def pop(self):#出栈
        return self.list.pop()
    def top(self):#返回顶部元素
        return self.list[len(self.list)-1]
    def size(self):#返回栈大小
        return len(self.list)

# 前缀表达式求值
def pretomid(x):
    s = Stack()
    list = x.split()#空格分割待字符串
    for par in list:
        if par in "+-*/":#遇到运算符则入栈
            s.push(par)
        else:   #为数字时分两种情况:
            if s.top() in '+-*/':#栈顶为运算符
                s.push(par)#数字入栈
            else:#当前栈顶为数字
                while (not s.isEmpty()) and (not s.top() in '+-*/'):#若栈不空,且当前栈顶为数字,则循环计算
                    shu = s.pop()#运算符前的数字出栈
                    fu = s.pop()#运算符出栈
                    par = '('+shu+fu+par+')'#计算
                s.push(str(par))#算式入栈
    return s.pop()#返回最终算式

n = input("请输入前缀表达式:")
print(pretomid(n))

# 输入 : * 2 3
# 输出(2*3)
# 错误输入: ( ^ ( / 5 2 ) 0.5 )
# 正确输入: ^ / 5 2 0.5

'如果想输入有括号的'
def pretomid(x):
    if '(' in x:
        x = x.replace('(', '').replace(')', '')
    s = Stack()
    list = x.split()#空格分割待字符串
    for par in list:
        if par in "+-*/^":#遇到运算符则入栈
            s.push(par)
        else:   #为数字时分两种情况:
            if s.top() in '+-*/^':#栈顶为运算符
                s.push(par)#数字入栈
            else:#当前栈顶为数字
                while (not s.isEmpty()) and (not s.top() in '+-*/^'):#若栈不空,且当前栈顶为数字,则循环计算
                    shu = s.pop()#运算符前的数字出栈
                    fu = s.pop()#运算符出栈
                    par = '('+shu+fu+par+')'#计算
                s.push(str(par))#算式入栈
    return s.pop()#返回最终算式
7.保存数据pickle
down_path = r'/home/zy/research/4_7/对比新旧模型的结果'
with open(os.path.join(down_path,'old_example.pkl'), 'wb') as f:
    pickle.dump(all_teacher, f)


with open(pre_pairs_path, 'rb') as f:
	pre_temp_pairs = pickle.load(f)
8.json存dict字典
json.loads(json_str) json字符串转换成字典
json.dumps(dict, ensure_ascii=False) 字典转换成json字符串
# 上面两个常用 一定要, ensure_ascii=False,不然就是assci,人不能阅读。


# 结合open文件写入一系列的dict字典。
all_dict = []
all_dict.append({error_check['id'] = d['id'], error_check['num_stack'] = problem[2]})
with open('error.txt', 'w') as f:
    for d in all_dict:
        f.write(json.dumps(d, ensure_ascii=False, indent=4)+'\n')
9.dict字典取值
x_dict = {'a':[1,2,3],'b':[2,3,4]}
x = ['a','b','a']
# 主要用了dict.get的方法,这个方法一般用于dict.get(键)得到值
# 但是不添加的话,就是提供了一个全体对象
list(map(x_dict.get, x))
10. 去掉string中的URL
pattern = re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+#]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+')

string = '根据[图片]https://www.umu.cn/course/index#/groups/5702006/sessions/37884166/view平台上面其他组建议,讨论修改自己组的内容,请抓紧'
url = re.sub(pattern, ' url ',string)
print(url)

三.模型函数

1.点积注意力
import torch
import torch.nn as nn
import numpy as np


class dot_attention(nn.Module):
    """ 点积注意力机制"""

    def __init__(self, attention_dropout=0.0):
        super(dot_attention, self).__init__()
        self.dropout = nn.Dropout(attention_dropout)
        self.softmax = nn.Softmax(dim=2)

    def forward(self, q, k, v, scale=None, attn_mask=None):
        """
        前向传播
        :param q:
        :param k:
        :param v:
        :param scale:
        :param attn_mask:
        :return: 上下文张量和attention张量。
        """
        attention = torch.bmm(q, k.transpose(1, 2))
        if scale:
            attention = attention * scale        # 是否设置缩放
        if attn_mask:
            attention = attention.masked_fill(attn_mask, -np.inf)     # 给需要mask的地方设置一个负无穷。
        # 计算softmax
        attention = self.softmax(attention)
        # 添加dropout
        attention = self.dropout(attention)
        # 和v做点积。
        context = torch.bmm(attention, v)
        return context, attention


if __name__ == '__main__':
    q = torch.ones((2, 3, 512))
    k = torch.ones((2, 17, 512))
    v = k
    attention = dot_attention()
    context, attention = attention(q, k, v)
    print("context:",  context, context.size())
    print("attention:", attention, attention.shape)
2.模型保存与加载
encoder = EncoderSeq(input_size, embedding_size, hidden_size,n_layers=n_layers)
predict = Prediction(hidden_size, op_nums,input_size)
generate = GenerateNode(hidden_size, op_nums, embedding_size)
merge = Merge(hidden_size, embedding_size)

# 加载
encoder.load_state_dict(torch.load(encoder_path))
predict.load_state_dict(torch.load(predict_path))
generate.load_state_dict(torch.load(generate_path))
merge.load_state_dict(torch.load(merge_path))

# 保存
torch.save(encoder.state_dict(), "model_traintest/encoder")
torch.save(predict.state_dict(), "model_traintest/predict")
torch.save(generate.state_dict(), "model_traintest/generate")
torch.save(merge.state_dict(), "model_traintest/merge")

四. 模型效果辅助函数

1.设定随机种子
rand = 1234
SEED = args.rand
torch.manual_seed(SEED) # 为CPU设置随机种子
torch.cuda.manual_seed(SEED) # 为当前GPU设置随机种子
np.random.seed(SEED) # 为np设定
random.seed(SEED) # 为random设定
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值