| 20 | |
| 21 | |
| 22 | def seqconv( |
| 23 | x, |
| 24 | lod, |
| 25 | filter, |
| 26 | context_length, |
| 27 | context_start, |
| 28 | padding_trainable=False, |
| 29 | padding_data=None, |
| 30 | ): |
| 31 | [T, M] = x.shape |
| 32 | col = np.zeros((T, context_length * M)).astype('float32') |
| 33 | offset = [0] |
| 34 | for seq_len in lod[0]: |
| 35 | offset.append(offset[-1] + seq_len) |
| 36 | begin_pad = np.max([0, -context_start]) |
| 37 | for i in range(len(offset) - 1): |
| 38 | for j in range(context_length): |
| 39 | in_begin = offset[i] + context_start + j |
| 40 | in_end = offset[i + 1] + context_start + j |
| 41 | out_begin = offset[i] |
| 42 | out_end = offset[i + 1] |
| 43 | if in_begin < offset[i]: |
| 44 | pad_size = np.min( |
| 45 | [offset[i] - in_begin, offset[i + 1] - offset[i]] |
| 46 | ) |
| 47 | if padding_trainable: |
| 48 | sub_w = padding_data[j : j + pad_size, :] |
| 49 | col[ |
| 50 | offset[i] : offset[i] + pad_size, j * M : (j + 1) * M |
| 51 | ] = sub_w |
| 52 | out_begin = offset[i] + pad_size |
| 53 | in_begin = offset[i] |
| 54 | |
| 55 | if in_end > offset[i + 1]: |
| 56 | pad_size = np.min( |
| 57 | [in_end - offset[i + 1], offset[i + 1] - offset[i]] |
| 58 | ) |
| 59 | if padding_trainable: |
| 60 | sub_w = padding_data[ |
| 61 | begin_pad + context_start + j - pad_size : begin_pad |
| 62 | + context_start |
| 63 | + j, |
| 64 | :, |
| 65 | ] |
| 66 | col[ |
| 67 | offset[i + 1] - pad_size : offset[i + 1], |
| 68 | j * M : (j + 1) * M, |
| 69 | ] = sub_w |
| 70 | in_end = offset[i + 1] |
| 71 | out_end = offset[i + 1] - pad_size |
| 72 | if in_end <= in_begin: |
| 73 | continue |
| 74 | in_sub = x[in_begin:in_end, :] |
| 75 | col[out_begin:out_end, j * M : (j + 1) * M] += in_sub |
| 76 | return np.dot(col, filter) |
| 77 | |
| 78 | |
| 79 | class TestSeqProject(OpTest): |