118 |

119 | 图3:分割出来的子序列(图源:Dive to Deep Learning)
120 |
121 |
122 | 如图3,不同的偏移量会导致产生不同的子序列。为了保证随机性,在这里选择随机偏移量作为起始位置。下面将实现随机采样和顺序分区来分割文本序列。
123 |
124 | ### 六. 随机采样
125 | 在随机采样(random sampling)中,每个子序列都是在原始长序列上任意捕获的短序列。在每次采样的过程中,采样之后两个相邻的子序列在原始长序列上不一定是相邻的。对于语言模型,特征(feature)是到目前为止能观测到的词元,而标签(label)则是位移了一个词元的原始序列。
126 | ```python
127 | def seq_data_iter_random(corpus, batch_size, num_steps): #num_steps为随即偏移量
128 | # 依据随即偏移量,对数据集进行顺序分区
129 | corpus = corpus[random.randint(0, num_steps-1):]
130 | # 计算子序列的数量
131 | num_subseqs = (len(corpus)-1) // num_steps
132 | # 建立长度为num_steps的子序列的起始索引
133 | indices = list(range(0, num_subseqs * num_steps, num_steps))
134 | random.shuffle(indices)
135 |
136 | def data(pos):
137 | # 返回指定区间长度的序列
138 | return corpus[pos: pos + num_steps]
139 |
140 | num_batches = num_subseqs // batch_size
141 | for i in range(0, num_batches * batch_size, batch_size):
142 | #每个batch的起始位置
143 | iter_indices_per_batch = indices[i: i + batch_size]
144 | X = [data(j) for j in iter_indices_per_batch]
145 | Y = [data(j + 1) for j in iter_indices_per_batch]
146 | # 保留一次迭代的特征和标签
147 | yield torch.tensor(X), torch.tensor(Y)
148 | ```
149 | 下面随机生成一个任意长度的序列来验证随机采样的效果。
150 |
151 | 设序列长度为34,时间步长为5,batch_size为2
152 | ```python
153 | seq = list(range(34))
154 | for X, Y in seq_data_iter_random(seq, 2, 5):
155 | print("X:",X, "\nY:", Y)
156 | ```
157 | 运行结果:
158 |
159 |