精华内容
下载资源
问答
  • 输出一个循环周期后就结束该数的输出1/7=0.142857n为2到50,如何顺序输出1/n的十进制表示的字符串(写出一个循环节为止)
  • Problem Description Zty很痴迷数学问题.。一天,yifenfei出了个数学题想难倒他... (是循环小数的,只输出第一个循环节). Sample Input 4 2 3 7 168 Sample Output 0.5 0.3 0.142857 0.005952380
  • 题目链接   题意是求前n个数的循环节的个数: 例如:aabaabaabaab中 , 前2个字符aa,循环节为a, 所以为2 2;...关键是如何循环节,首先还要熟悉next数组的意思,next[j]=k,表示j前面k个元素与...

    题目链接

     

    题意是求前n个数的循环节的个数:

    例如:aabaabaabaab中 ,

    前2个字符aa,循环节为a, 所以为2 2;

    前6 个 字符循环节为aab,  所以为6 2;

    前9个 字符循环节为aab,   所以为9 3;

    前12 个 字符循环节为aab,所以为12 4;

     

    关键是如何求循环节,首先还要熟悉next数组的意思,next[j]=k,表示j前面k个元素与开头的前k个元素相同,但是中间可能有循环的元素,如何去除重复的元素

    i 0 1 2 3 4 5 6 7 8 9 10 11 12
    a[i] a a b a a b a a b a a b  
    next[i] -1 0 1 0 1 2 3 4 5 6 7 8 9

     

     2*next[i]-i即可以求出中间重复的元素;

    (原因:初中因该学过,给N个元素,前k个元素和后k个元素相等,求重复的元素个数)

    next[i]-(2*next[i]-i) == i-next[i]即是最小的循环节;

    i/最小循环节  =  循环的次数 ;

     

     

    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    const int MAX = 1000000 + 5;
    int next[MAX],len;
    char a[MAX];
    
    void get_next()
    {
    	int i=0,j=-1;
    	next[0]=-1;
    	while(i<len) 
    	{
    		while(j>-1&&a[j]!=a[i])
    			j=next[j];
    		j++;
    		i++;
    		next[i]=j;
    	}
    }
    
    int main()
    {
    	int ncase=0;
    	while(scanf("%d",&len)&&len)
    	{
    		scanf("%s",a);
    		int circle; 
    		get_next();
    		printf("Test case #%d\n",++ncase);
    		for(int i=1;i<=len;i++)
    		{
    			circle=next[i]-(2*next[i]-i);
    			if(2*next[i]-i>=0 && i%circle == 0)
    			{
    				printf("%d %d\n",i,i/circle);
    			}
    		}
    		printf("\n");
    	}
    	return 0;
    }

     

    展开全文
  • 一、Problem 给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式...方法一:map + 记录循环节 思考 分子分母有负数;小数部分如何处理呢; 思路 小数部分可以通过模拟除法完成,关键是处理

    一、Problem

    给定两个整数,分别表示分数的分子 numerator 和分母 denominator,以字符串形式返回小数。

    如果小数部分为循环小数,则将循环的部分括在括号内

    输入: numerator = 1, denominator = 2
    输出: "0.5"
    
    输入: numerator = 2, denominator = 3
    输出: "0.(6)"
    

    二、Solution

    方法一:map + 记录循环节

    思考

    分子分母有负数;小数部分如何处理呢;

    思路

    小数部分可以通过模拟除法完成,关键是处理循环小数:

    • 非循环小数:余数在进行除法的时候会变为 0
    • 循环小数:循环这个词很直观,循环节的长度第二次与第一次出现同一数字时的距离

    这两种样例可以心态炸裂…

    -1
    -2147483648
    
    -2147483648
    1
    
    细节:
    0
    -5
    
    class Solution {
    public:
        string fractionToDecimal(int u, int d) {
            if (u==0) return "0";
            string ans, loop;
            if (u < 0 && d > 0 || d < 0 && u > 0)
                ans = "-";
            d=abs(d), u=abs(u); 
            long a=u/d, b= u%d;
            ans.append(to_string(a));
            if (b==0) return ans;
            
            ans.append(".");
            unordered_map<long, int> map;
            int i=0, hasLoop=true;
            
            while (map.find(b) == map.end()) {
                map[b]=i++;
                b*=10;
                int aa=b/d, bb=b%d;
                loop.append(to_string(aa));
                if (bb==0) {
                    hasLoop=false;
                    break;
                }
                b=bb;
            }
            // loop which was loop.substr(map[b]),but still has noLoop part:loop.substr(0, map[b])
            if (hasLoop) {
                ans.append(loop.substr(0, map[b])), ans.append("(");
                ans.append(loop.substr(map[b])), ans.append(")");
            } else {
                ans.append(loop);
            }
            return ans;
        }
    };
    

    复杂度分析

    • TimeO(n)O(n)
    • SpaceO(n)O(n)
    展开全文
  • 先来看一些例:(无法在3上记点,故在3前后以一“~”号代替,表示其从“~”号处开始无限循环)7/3=2.~3333~ 10/3=3.~33333~ 31/3=10.~3~ 127/3=42.~3~ 。。。。。好了,如何求出符合这样要求的正整数呢?我们...

    先来看一些例:(无法在3上记点,故在3前后以一“~”号代替,表示其从“~”号处开始无限循环)

    7/3=2.~3333~          10/3=3.~33333~        31/3=10.~3~         127/3=42.~3~       。。。。。

    好了,如何求出符合这样要求的正整数呢?

    我们发现,所有这些数除以3的余数都为一。

    搞定。

    谈点别的,看下这个:

    0/3    1/3=0.~3~    2/3=0.~6~    3/3=1     4/3=1.~3~    5/3=1.~6~   6/3=2    7/3=2.~3~   8/3=2.~6~     9/3=3    10/3=3.~3~

    怎么样看出什么名堂没有。好,再来:

    0/1     1/1=1            2/1= 2           3/1=3           4/1=4           5/1=5              6/1=6             7/1=7                  8/1=8           9/1=9             10/1=10

    0/2     1/2=0.5          2/2=1           3/2=1.5         4/2=2           5/2=2.5           6/2=3              7/2=3.5               8/2=4           9/2=4.5           10/2=5

    0/4     1/4=0.25        2/4 =0.5        3/4=0.75        4/4=1          5/4=1.25          6/4=1.5           7/4=1.75             8/4=2           9/4=2.25            10/4=2.5

    0/5    1/5=0.25

    0/6    1/6=0.~6~

    0/7     1/7=0.~142857~

    0/8     1/8=0.125

    0/9     1/9=0.~1~

    0/10   1/10=0.1

    也许你会问看这个有什么用?(是不是吃多了饭没事做呢?:)

    注意这些答案都是很有规律的是不用“计算”就能得出来的。

    那么这些所谓的规律是什么呢?

    这里我引入一个概念,叫跳数。为什么要叫跳数呢?因为跳是需要能量的给人以充满力量的摆脱束缚跨越障碍的感觉(当然干任何事情都是需要转化能量的,除非你变成空间,那么能量就不再运动,能量就变成最原始的状态),把一个数等分仍然是需要转化能量的,跳得高矮,远近受转化能量的大小控制,等份的多少也受转化能量多少的支配,能量是最具有惰性的一种物质,他有想静止不动的特性(这是由于空间这种物质都是挤压在一起的,无法动弹),也就是说无限趋向于静止,所以有把一切拉回到静止状态的趋势,为了跨越并摆脱这种障碍所需要转化的能量的大小可以与任意维数上的空间中的位置建立一一对应的关系。也就是说为了克服无限大无限小的空间的阻碍需要暂时用能量把他挤开,以获得通过或占据他们的位置。这就是为什么数列、矩阵和维度空间都无限趋向或远离某一点的原因,也就是从什么地方开始在什么地方结束的问题。但是空间的分布按照需要并不是连续的,所以需要计算“跳”到另一个空间位置上去所需要的能量的一种计量单位。(想象一下水或者空气吧,有助于理解的。谈得太快了,拉回来,慢慢来)。

    跳数是什么呢,实际上是一个数值(振幅),简单的说就是指一个数(空间)可以被等分成多少个另一个数(相互隔离的或抽象的或连续的空间)的值。

    上面表中所有等号右边的数都是跳数值,横向的行叫衰减行(具有方向时是趋向于原发的衰减),第一行等号右边的数叫跳数。第二行以后的行中等号右边的数都是一个值(乘积),不是跳数,称跳跃值简称跳跃或跳。再来看一下列,右数第一列叫原发列

    第二列叫基跳列(这一列的所有跳都叫基跳数值简称基跳数或基跳[能量跃迁的值]。右数第三列以后的可以依次叫一,二,三。。。等等跳列都可以,不是固定的)。斜向的叫断裂区段,也是有方向的(分得比较复杂暂且放到一边。)

    好了,结果出来也。

    (概念其实是什么不重要,重要的是好理解就行了,估计上面的也不是很好理解。如果你愿意叫他什么都无所谓,比如叫步长、振幅啊什么的,叫白痴也没所谓,呵呵。)

    估计也没人感兴趣的东西。

     

    展开全文
  • 循环神经网络

    2020-02-19 17:42:14
    介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量H,用Ht表示H在时间步t的值。Ht的计算基于...

    循环神经网络
    本节介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量H,用Ht表示H在时间步t的值。Ht的计算基于Xt和Ht−1,可以认为Ht记录了到当前字符为止的序列信息,利用Ht对序列的下一个字符进行预测。
    在这里插入图片描述

    循环神经网络的构造
    我们先看循环神经网络的具体构造。假设Xt∈Rn×d是时间步t的小批量输入,Ht∈Rn×h是该时间步的隐藏变量,则:

    在这里插入图片描述
    其中,Wxh∈Rd×h,Whh∈Rh×h,bh∈R1×h,ϕ函数是非线性激活函数。由于引入了Ht−1Whh,Ht能够捕捉截至当前时间步的序列的历史信息,就像是神经网络当前时间步的状态或记忆一样。由于Ht的计算基于Ht−1,上式的计算是循环的,使用循环计算的网络即循环神经网络(recurrent neural network)。

    在时间步t,输出层的输出为:

    在这里插入图片描述
    其中Whq∈Rh×q,bq∈R1×q。

    从零开始实现循环神经网络
    我们先尝试从零开始实现一个基于字符级循环神经网络的语言模型,这里我们使用周杰伦的歌词作为语料,首先我们读入数据:

    In [1]:
    import torch
    import torch.nn as nn
    import time
    import math
    import sys
    sys.path.append("/home/kesci/input")
    import d2l_jay9460 as d2l
    (corpus_indices, char_to_idx, idx_to_char, vocab_size) = d2l.load_data_jay_lyrics()
    device = torch.device(‘cuda’ if torch.cuda.is_available() else ‘cpu’)
    one-hot向量
    我们需要将字符表示成向量,这里采用one-hot向量。假设词典大小是N,每次字符对应一个从0到N−1的唯一的索引,则该字符的向量是一个长度为N的向量,若字符的索引是i,则该向量的第i个位置为1,其他位置为0。下面分别展示了索引为0和2的one-hot向量,向量长度等于词典大小。

    In [2]:
    def one_hot(x, n_class, dtype=torch.float32):
    result = torch.zeros(x.shape[0], n_class, dtype=dtype, device=x.device) # shape: (n, n_class)
    result.scatter_(1, x.long().view(-1, 1), 1) # result[i, x[i, 0]] = 1
    return result

    x = torch.tensor([0, 2])
    x_one_hot = one_hot(x, vocab_size)
    print(x_one_hot)
    print(x_one_hot.shape)
    print(x_one_hot.sum(axis=1))
    tensor([[1., 0., 0., …, 0., 0., 0.],
    [0., 0., 1., …, 0., 0., 0.]])
    torch.Size([2, 1027])
    tensor([1., 1.])
    我们每次采样的小批量的形状是(批量大小, 时间步数)。下面的函数将这样的小批量变换成数个形状为(批量大小, 词典大小)的矩阵,矩阵个数等于时间步数。也就是说,时间步t的输入为Xt∈Rn×d,其中n为批量大小,d为词向量大小,即one-hot向量长度(词典大小)。

    In [3]:
    def to_onehot(X, n_class):
    return [one_hot(X[:, i], n_class) for i in range(X.shape[1])]

    X = torch.arange(10).view(2, 5)
    inputs = to_onehot(X, vocab_size)
    print(len(inputs), inputs[0].shape)
    5 torch.Size([2, 1027])
    初始化模型参数
    In [4]:
    num_inputs, num_hiddens, num_outputs = vocab_size, 256, vocab_size
    def get_params():
    def one(shape):
    param = torch.zeros(shape, device=device, dtype=torch.float32)
    nn.init.normal
    (param, 0, 0.01)
    return torch.nn.Parameter(param)

    # 隐藏层参数
    W_xh = _one((num_inputs, num_hiddens))
    W_hh = _one((num_hiddens, num_hiddens))
    b_h = torch.nn.Parameter(torch.zeros(num_hiddens, device=device))
    # 输出层参数
    W_hq = _one((num_hiddens, num_outputs))
    b_q = torch.nn.Parameter(torch.zeros(num_outputs, device=device))
    return (W_xh, W_hh, b_h, W_hq, b_q)
    

    定义模型
    函数rnn用循环的方式依次完成循环神经网络每个时间步的计算。

    In [5]:
    def rnn(inputs, state, params):
    # inputs和outputs皆为num_steps个形状为(batch_size, vocab_size)的矩阵
    W_xh, W_hh, b_h, W_hq, b_q = params
    H, = state
    outputs = []
    for X in inputs:
    H = torch.tanh(torch.matmul(X, W_xh) + torch.matmul(H, W_hh) + b_h)
    Y = torch.matmul(H, W_hq) + b_q
    outputs.append(Y)
    return outputs, (H,)
    函数init_rnn_state初始化隐藏变量,这里的返回值是一个元组。

    In [6]:
    def init_rnn_state(batch_size, num_hiddens, device):
    return (torch.zeros((batch_size, num_hiddens), device=device), )
    做个简单的测试来观察输出结果的个数(时间步数),以及第一个时间步的输出层输出的形状和隐藏状态的形状。

    In [7]:
    print(X.shape)
    print(num_hiddens)
    print(vocab_size)
    state = init_rnn_state(X.shape[0], num_hiddens, device)
    inputs = to_onehot(X.to(device), vocab_size)
    params = get_params()
    outputs, state_new = rnn(inputs, state, params)
    print(len(inputs), inputs[0].shape)
    print(len(outputs), outputs[0].shape)
    print(len(state), state[0].shape)
    print(len(state_new), state_new[0].shape)
    torch.Size([2, 5])
    256
    1027
    5 torch.Size([2, 1027])
    5 torch.Size([2, 1027])
    1 torch.Size([2, 256])
    1 torch.Size([2, 256])
    裁剪梯度
    循环神经网络中较容易出现梯度衰减或梯度爆炸,这会导致网络几乎无法训练。裁剪梯度(clip gradient)是一种应对梯度爆炸的方法。假设我们把所有模型参数的梯度拼接成一个向量 g,并设裁剪的阈值是θ。裁剪后的梯度

    min(θ‖g‖,1)g
    的L2范数不超过θ。

    In [8]:
    def grad_clipping(params, theta, device):
    norm = torch.tensor([0.0], device=device)
    for param in params:
    norm += (param.grad.data ** 2).sum()
    norm = norm.sqrt().item()
    if norm > theta:
    for param in params:
    param.grad.data *= (theta / norm)
    定义预测函数
    以下函数基于前缀prefix(含有数个字符的字符串)来预测接下来的num_chars个字符。这个函数稍显复杂,其中我们将循环神经单元rnn设置成了函数参数,这样在后面小节介绍其他循环神经网络时能重复使用这个函数。

    In [9]:
    def predict_rnn(prefix, num_chars, rnn, params, init_rnn_state,
    num_hiddens, vocab_size, device, idx_to_char, char_to_idx):
    state = init_rnn_state(1, num_hiddens, device)
    output = [char_to_idx[prefix[0]]] # output记录prefix加上预测的num_chars个字符
    for t in range(num_chars + len(prefix) - 1):
    # 将上一时间步的输出作为当前时间步的输入
    X = to_onehot(torch.tensor([[output[-1]]], device=device), vocab_size)
    # 计算输出和更新隐藏状态
    (Y, state) = rnn(X, state, params)
    # 下一个时间步的输入是prefix里的字符或者当前的最佳预测字符
    if t < len(prefix) - 1:
    output.append(char_to_idx[prefix[t + 1]])
    else:
    output.append(Y[0].argmax(dim=1).item())
    return ‘’.join([idx_to_char[i] for i in output])
    我们先测试一下predict_rnn函数。我们将根据前缀“分开”创作长度为10个字符(不考虑前缀长度)的一段歌词。因为模型参数为随机值,所以预测结果也是随机的。

    In [10]:
    predict_rnn(‘分开’, 10, rnn, params, init_rnn_state, num_hiddens, vocab_size,
    device, idx_to_char, char_to_idx)
    Out[10]:
    ‘分开濡时食提危踢拆田唱母’
    困惑度
    我们通常使用困惑度(perplexity)来评价语言模型的好坏。回忆一下“softmax回归”一节中交叉熵损失函数的定义。困惑度是对交叉熵损失函数做指数运算后得到的值。特别地,

    最佳情况下,模型总是把标签类别的概率预测为1,此时困惑度为1;
    最坏情况下,模型总是把标签类别的概率预测为0,此时困惑度为正无穷;
    基线情况下,模型总是预测所有类别的概率都相同,此时困惑度为类别个数。
    显然,任何一个有效模型的困惑度必须小于类别个数。在本例中,困惑度必须小于词典大小vocab_size。

    定义模型训练函数
    跟之前章节的模型训练函数相比,这里的模型训练函数有以下几点不同:

    使用困惑度评价模型。
    在迭代模型参数前裁剪梯度。
    对时序数据采用不同采样方法将导致隐藏状态初始化的不同。
    In [11]:
    def train_and_predict_rnn(rnn, get_params, init_rnn_state, num_hiddens,
    vocab_size, device, corpus_indices, idx_to_char,
    char_to_idx, is_random_iter, num_epochs, num_steps,
    lr, clipping_theta, batch_size, pred_period,
    pred_len, prefixes):
    if is_random_iter:
    data_iter_fn = d2l.data_iter_random
    else:
    data_iter_fn = d2l.data_iter_consecutive
    params = get_params()
    loss = nn.CrossEntropyLoss()

    for epoch in range(num_epochs):
        if not is_random_iter:  # 如使用相邻采样,在epoch开始时初始化隐藏状态
            state = init_rnn_state(batch_size, num_hiddens, device)
        l_sum, n, start = 0.0, 0, time.time()
        data_iter = data_iter_fn(corpus_indices, batch_size, num_steps, device)
        for X, Y in data_iter:
            if is_random_iter:  # 如使用随机采样,在每个小批量更新前初始化隐藏状态
                state = init_rnn_state(batch_size, num_hiddens, device)
            else:  # 否则需要使用detach函数从计算图分离隐藏状态
                for s in state:
                    s.detach_()
            # inputs是num_steps个形状为(batch_size, vocab_size)的矩阵
            inputs = to_onehot(X, vocab_size)
            # outputs有num_steps个形状为(batch_size, vocab_size)的矩阵
            (outputs, state) = rnn(inputs, state, params)
            # 拼接之后形状为(num_steps * batch_size, vocab_size)
            outputs = torch.cat(outputs, dim=0)
            # Y的形状是(batch_size, num_steps),转置后再变成形状为
            # (num_steps * batch_size,)的向量,这样跟输出的行一一对应
            y = torch.flatten(Y.T)
            # 使用交叉熵损失计算平均分类误差
            l = loss(outputs, y.long())
            
            # 梯度清0
            if params[0].grad is not None:
                for param in params:
                    param.grad.data.zero_()
            l.backward()
            grad_clipping(params, clipping_theta, device)  # 裁剪梯度
            d2l.sgd(params, lr, 1)  # 因为误差已经取过均值,梯度不用再做平均
            l_sum += l.item() * y.shape[0]
            n += y.shape[0]
    
        if (epoch + 1) % pred_period == 0:
            print('epoch %d, perplexity %f, time %.2f sec' % (
                epoch + 1, math.exp(l_sum / n), time.time() - start))
            for prefix in prefixes:
                print(' -', predict_rnn(prefix, pred_len, rnn, params, init_rnn_state,
                    num_hiddens, vocab_size, device, idx_to_char, char_to_idx))
    

    训练模型并创作歌词
    现在我们可以训练模型了。首先,设置模型超参数。我们将根据前缀“分开”和“不分开”分别创作长度为50个字符(不考虑前缀长度)的一段歌词。我们每过50个迭代周期便根据当前训练的模型创作一段歌词。

    In [12]:
    num_epochs, num_steps, batch_size, lr, clipping_theta = 250, 35, 32, 1e2, 1e-2
    pred_period, pred_len, prefixes = 50, 50, [‘分开’, ‘不分开’]
    下面采用随机采样训练模型并创作歌词。

    In [13]:
    train_and_predict_rnn(rnn, get_params, init_rnn_state, num_hiddens,
    vocab_size, device, corpus_indices, idx_to_char,
    char_to_idx, True, num_epochs, num_steps, lr,
    clipping_theta, batch_size, pred_period, pred_len,
    prefixes)
    epoch 50, perplexity 65.808092, time 0.78 sec

    • 分开 我想要这样 我不要再想 我不要再想 我不要再想 我不要再想 我不要再想 我不要再想 我不要再想 我
    • 不分开 别颗去 一颗两 三颗四 一颗四 三颗四 一颗四 一颗四 一颗四 一颗四 一颗四 一颗四 一颗四 一
      epoch 100, perplexity 9.794889, time 0.72 sec
    • 分开 一直在美留 谁在它停 在小村外的溪边 默默等 什么 旧你在依旧 我有儿有些瘦 世色我遇见你是一场
    • 不分开吗 我不能再想 我不 我不 我不 我不 我不 我不 我不 我不 我不 我不 我不 我不 我不 我不
      epoch 150, perplexity 2.772557, time 0.80 sec
    • 分开 有直在不妥 有话它停留 蜥蝪横怕落 不爽就 旧怪堂 是属于依 心故之 的片段 有一些风霜 老唱盘
    • 不分开吗 然后将过不 我慢 失些 如 静里回的太快 想通 却又再考倒我 说散 你想很久了吧?的我 从等
      epoch 200, perplexity 1.601744, time 0.73 sec
    • 分开 那只都它满在我面妈 捏成你的形状啸而过 或愿说在后能 让梭时忆对着轻轻 我想就这样牵着你的手不放开
    • 不分开期 然后将过去 慢慢温习 让我爱上你 那场悲剧 是你完美演出的一场戏 宁愿心碎哭泣 再狠狠忘记 不是
      epoch 250, perplexity 1.323342, time 0.78 sec
    • 分开 出愿段的哭咒的天蛦丘好落 拜托当血穿永杨一定的诗篇 我给你的爱写在西元前 深埋在美索不达米亚平原
    • 不分开扫把的胖女巫 用拉丁文念咒语啦啦呜 她养的黑猫笑起来像哭 啦啦啦呜 我来了我 在我感外的溪边河口默默
      接下来采用相邻采样训练模型并创作歌词。

    In [14]:
    train_and_predict_rnn(rnn, get_params, init_rnn_state, num_hiddens,
    vocab_size, device, corpus_indices, idx_to_char,
    char_to_idx, False, num_epochs, num_steps, lr,
    clipping_theta, batch_size, pred_period, pred_len,
    prefixes)
    epoch 50, perplexity 60.294393, time 0.74 sec

    • 分开 我想要你想 我不要再想 我不要再想 我不要再想 我不要再想 我不要再想 我不要再想 我不要再想 我
    • 不分开 我想要你 你有了 别不我的可爱女人 坏坏的让我疯狂的可爱女人 坏坏的让我疯狂的可爱女人 坏坏的让我
      epoch 100, perplexity 7.141162, time 0.72 sec
    • 分开 我已要再爱 我不要再想 我不 我不 我不要再想 我不 我不 我不要 爱情我的见快就像龙卷风 离能开
    • 不分开柳 你天黄一个棍 后知哈兮 快使用双截棍 哼哼哈兮 快使用双截棍 哼哼哈兮 快使用双截棍 哼哼哈兮
      epoch 150, perplexity 2.090277, time 0.73 sec
    • 分开 我已要这是你在著 不想我都做得到 但那个人已经不是我 没有你在 我却多难熬 没有你在我有多难熬多
    • 不分开觉 你已经离 我想再好 这样心中 我一定带我 我的完空 不你是风 一一彩纵 在人心中 我一定带我妈走
      epoch 200, perplexity 1.305391, time 0.77 sec
    • 分开 我已要这样牵看你的手 它一定实现它一定像现 载著你 彷彿载著阳光 不管到你留都是晴天 蝴蝶自在飞力
    • 不分开觉 你已经离开我 不知不觉 我跟了这节奏 后知后觉 又过了一个秋 后知后觉 我该好好生活 我该好好生
      epoch 250, perplexity 1.230800, time 0.79 sec
    • 分开 我不要 是你看的太快了悲慢 担心今手身会大早 其么我也睡不着 昨晚梦里你来找 我才 原来我只想
    • 不分开觉 你在经离开我 不知不觉 你知了有节奏 后知后觉 后知了一个秋 后知后觉 我该好好生活 我该好好生
      循环神经网络的简介实现
      定义模型
      我们使用Pytorch中的nn.RNN来构造循环神经网络。在本节中,我们主要关注nn.RNN的以下几个构造函数参数:

    input_size - The number of expected features in the input x
    hidden_size – The number of features in the hidden state h
    nonlinearity – The non-linearity to use. Can be either ‘tanh’ or ‘relu’. Default: ‘tanh’
    batch_first – If True, then the input and output tensors are provided as (batch_size, num_steps, input_size). Default: False
    这里的batch_first决定了输入的形状,我们使用默认的参数False,对应的输入形状是 (num_steps, batch_size, input_size)。

    forward函数的参数为:

    input of shape (num_steps, batch_size, input_size): tensor containing the features of the input sequence.
    h_0 of shape (num_layers * num_directions, batch_size, hidden_size): tensor containing the initial hidden state for each element in the batch. Defaults to zero if not provided. If the RNN is bidirectional, num_directions should be 2, else it should be 1.
    forward函数的返回值是:

    output of shape (num_steps, batch_size, num_directions * hidden_size): tensor containing the output features (h_t) from the last layer of the RNN, for each t.
    h_n of shape (num_layers * num_directions, batch_size, hidden_size): tensor containing the hidden state for t = num_steps.
    现在我们构造一个nn.RNN实例,并用一个简单的例子来看一下输出的形状。

    In [15]:
    rnn_layer = nn.RNN(input_size=vocab_size, hidden_size=num_hiddens)
    num_steps, batch_size = 35, 2
    X = torch.rand(num_steps, batch_size, vocab_size)
    state = None
    Y, state_new = rnn_layer(X, state)
    print(Y.shape, state_new.shape)
    torch.Size([35, 2, 256]) torch.Size([1, 2, 256])
    我们定义一个完整的基于循环神经网络的语言模型。

    In [16]:
    class RNNModel(nn.Module):
    def init(self, rnn_layer, vocab_size):
    super(RNNModel, self).init()
    self.rnn = rnn_layer
    self.hidden_size = rnn_layer.hidden_size * (2 if rnn_layer.bidirectional else 1)
    self.vocab_size = vocab_size
    self.dense = nn.Linear(self.hidden_size, vocab_size)

    def forward(self, inputs, state):
        # inputs.shape: (batch_size, num_steps)
        X = to_onehot(inputs, vocab_size)
        X = torch.stack(X)  # X.shape: (num_steps, batch_size, vocab_size)
        hiddens, state = self.rnn(X, state)
        hiddens = hiddens.view(-1, hiddens.shape[-1])  # hiddens.shape: (num_steps * batch_size, hidden_size)
        output = self.dense(hiddens)
        return output, state
    

    类似的,我们需要实现一个预测函数,与前面的区别在于前向计算和初始化隐藏状态。

    In [17]:
    def predict_rnn_pytorch(prefix, num_chars, model, vocab_size, device, idx_to_char,
    char_to_idx):
    state = None
    output = [char_to_idx[prefix[0]]] # output记录prefix加上预测的num_chars个字符
    for t in range(num_chars + len(prefix) - 1):
    X = torch.tensor([output[-1]], device=device).view(1, 1)
    (Y, state) = model(X, state) # 前向计算不需要传入模型参数
    if t < len(prefix) - 1:
    output.append(char_to_idx[prefix[t + 1]])
    else:
    output.append(Y.argmax(dim=1).item())
    return ‘’.join([idx_to_char[i] for i in output])
    使用权重为随机值的模型来预测一次。

    In [18]:
    model = RNNModel(rnn_layer, vocab_size).to(device)
    predict_rnn_pytorch(‘分开’, 10, model, vocab_size, device, idx_to_char, char_to_idx)
    Out[18]:
    ‘分开胸呵以轮轮轮轮轮轮轮’
    接下来实现训练函数,这里只使用了相邻采样。

    In [19]:
    def train_and_predict_rnn_pytorch(model, num_hiddens, vocab_size, device,
    corpus_indices, idx_to_char, char_to_idx,
    num_epochs, num_steps, lr, clipping_theta,
    batch_size, pred_period, pred_len, prefixes):
    loss = nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=lr)
    model.to(device)
    for epoch in range(num_epochs):
    l_sum, n, start = 0.0, 0, time.time()
    data_iter = d2l.data_iter_consecutive(corpus_indices, batch_size, num_steps, device) # 相邻采样
    state = None
    for X, Y in data_iter:
    if state is not None:
    # 使用detach函数从计算图分离隐藏状态
    if isinstance (state, tuple): # LSTM, state:(h, c)
    state[0].detach_()
    state[1].detach_()
    else:
    state.detach_()
    (output, state) = model(X, state) # output.shape: (num_steps * batch_size, vocab_size)
    y = torch.flatten(Y.T)
    l = loss(output, y.long())

            optimizer.zero_grad()
            l.backward()
            grad_clipping(model.parameters(), clipping_theta, device)
            optimizer.step()
            l_sum += l.item() * y.shape[0]
            n += y.shape[0]
        
    
        if (epoch + 1) % pred_period == 0:
            print('epoch %d, perplexity %f, time %.2f sec' % (
                epoch + 1, math.exp(l_sum / n), time.time() - start))
            for prefix in prefixes:
                print(' -', predict_rnn_pytorch(
                    prefix, pred_len, model, vocab_size, device, idx_to_char,
                    char_to_idx))
    

    训练模型。

    In [20]:
    num_epochs, batch_size, lr, clipping_theta = 250, 32, 1e-3, 1e-2
    pred_period, pred_len, prefixes = 50, 50, [‘分开’, ‘不分开’]
    train_and_predict_rnn_pytorch(model, num_hiddens, vocab_size, device,
    corpus_indices, idx_to_char, char_to_idx,
    num_epochs, num_steps, lr, clipping_theta,
    batch_size, pred_period, pred_len, prefixes)
    epoch 50, perplexity 9.405654, time 0.52 sec

    • 分开始一起 三步四步望著天 看星星 一颗两颗三颗四颗 连成线背著背默默许下心愿 一枝杨柳 你的那我 在
    • 不分开 爱情你的手 一人的老斑鸠 腿短毛不多 快使用双截棍 哼哼哈兮 快使用双截棍 哼哼哈兮 快使用双截棍
      epoch 100, perplexity 1.255020, time 0.54 sec
    • 分开 我人了的屋我 一定令它心仪的母斑鸠 爱像一阵风 吹完美主 这样 还人的太快就是学怕眼口让我碰恨这
    • 不分开不想我多的脑袋有问题 随便说说 其实我早已经猜透看透不想多说 只是我怕眼泪撑不住 不懂 你的黑色幽默
      epoch 150, perplexity 1.064527, time 0.53 sec
    • 分开 我轻外的溪边 默默在一心抽离 有话不知不觉 一场悲剧 我对不起 藤蔓植物的爬满了伯爵的坟墓 古堡里
    • 不分开不想不多的脑 有教堂有你笑 我有多烦恼 没有你烦 有有样 别怪走 快后悔没说你 我不多难熬 我想就
      epoch 200, perplexity 1.033074, time 0.53 sec
    • 分开 我轻外的溪边 默默在一心向昏 的愿 古无着我只能 一个黑远 这想太久 这样我 不要再是你打我妈妈
    • 不分开你只会我一起睡著 样 娘子却只想你和汉堡 我想要你的微笑每天都能看到 我知道这里很美但家乡的你更美
      epoch 250, perplexity 1.047890, time 0.68 sec
    • 分开 我轻多的漫 却已在你人演 想要再直你 我想要这样牵着你的手不放开 爱可不可以简简单单没有伤害 你
    • 不分开不想不多的假 已无能为力再提起 决定中断熟悉 然后在这里 不限日期 然后将过去 慢慢温习 让我爱上
    展开全文
  • Python小白变大神之while循环课我们介绍了for循环,以及嵌套的多重for循环的程序如何编写。今天我们要介绍另一种循环:while循环while循环比for循环简单,更容易理解。我们一起来学习一下吧~while循环基本语法...
  • Python小白变大神之while循环课我们介绍了for循环,以及嵌套的多重for循环的程序如何编写。今天我们要介绍另一种循环:while循环while循环比for循环简单,更容易理解。我们一起来学习一下吧~while循环基本语法...
  • 将介绍循环神经⽹络。它并⾮刚性地记忆所有固定⻓度的序列,而是通过隐藏状态来储存之前时间步的信息。⾸先我们回忆⼀下前⾯介绍过的多层感知机,然后描述如何添加隐藏状态来将它变成循环神经⽹络。 一、不含...
  • 循环神经网络基础

    2020-02-19 14:32:20
    介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH在时间步ttt的值...
  • L6循环神经网络

    2020-02-14 14:31:06
    介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH在时间步ttt的值...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量H,用Ht表示H在时间步t的值。Ht的计算基于...
  • 将分数表示为任意进制的小数

    千次阅读 2013-11-19 13:14:56
    看后很有收获,然后突然就想到了这么个问题,如何编个程序将有理数的分数表示转换为小数表示,并且对于无限循环小数还要给出循环节来。 花了半天时间将程序写好调通。把程序放在这里做个记录。
  • pytorch-循环神经网络

    2020-02-14 20:17:33
    介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH在时间步ttt的值...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量 H ,用 Ht 表示 H 在时间步 t 的值。 Ht ...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量,用表示在时间步的值。的计算基于和,可以...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。其目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_tHt​表示HHH在时间步ttt的值。HtH_...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HH,用HtHt表示HH在时间步tt的值。HtHt的...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH在时间步ttt的值...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH在时间步ttt的值...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HH,用HtHt表示HH在时间步tt的值。HtHt的...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。 从零开始实现循环神经网络 我们先尝试从零开始实现一个基于字符级循环神经网络的语言模型,这里我们使用周杰伦的歌词作为语料,首先我们读入...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH在时间步ttt的值...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH在时间步ttt的值...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH在时间步ttt的值...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH在时间步ttt的值...
  • 介绍循环神经网络,下图展示了如何基于循环神经网络实现语言模型。我们的目的是基于当前的输入与过去的输入序列,预测序列的下一个字符。循环神经网络引入一个隐藏变量HHH,用HtH_{t}Ht​表示HHH在时间步ttt的值...
  • kmp+最大最小表示

    2020-06-19 18:16:44
    出现次数应该都知道是最小循环节的个数。关键如何找到最小字典序和最大字典序。 网上可以搜到最大最小表示的讲解和代码,设p1= 0, p2 = 0,k = 0;如果s[p1]和s[p2]不相等了,那么p1或p2就会跳,假设p1跳到p1+k+1的...
  • 你会看到我们如何把这些知识用到NLP上,用于自然语言处理,深度学习已经给这一领域带来了革命性的变革。其中一个很关键的概念就是词嵌入(word embeddings),这是语言表示的一种方式,可以让算法自动的理解一些...

空空如也

空空如也

1 2 3 4 5
收藏数 87
精华内容 34
关键字:

如何表示循环节