“Kỷ nguyên” của Transformers

Mar 27 2023
Xử lý toàn bộ kỷ nguyên Numerai cùng một lúc với Transformers. Chỉ cần đưa cho tôi mã ️: GPU -> Chạy tất cả sổ ghi chép tạo tệp gửi.

Xử lý toàn bộ kỷ nguyên Numerai cùng một lúc với Transformers.

Chỉ cần cho tôi mã ️:

GPU -> Chạy tất cả sổ ghi chép tạo tệp gửi. Chạy với 15 phút.

Nếu bạn chưa quen với các giải đấu của Numer.ai, các bài đăng sau đây có thể hữu ích để hiểu ngữ cảnh về bài đăng này.

Dữ liệu (Kỷ nguyên) ⌗

Tập dữ liệu được cung cấp ( v4.1: Sunshine ) chứa dữ liệu thị trường chứng khoán bị xáo trộn trong những thập kỷ qua được chia thành các nhóm có tên là “Kỷ nguyên” (một số nguyên). Các thời đại đại diện cho một ý nghĩa tương đối về thời gian, nghĩa là thời đại 1 xảy ra trước thời đại 2 và cứ thế cho đến tổng cộng khoảng 1050 thời đại. Chúng được chia thành các bộ đào tạo và xác nhận.

Minh họa tập dữ liệu V2; https://docs.numer.ai/tournament/learn

Kỷ nguyên như một trình tự ⠿

Hầu hết các mô hình coi mỗi hàng là một mẫu mà không có bất kỳ bối cảnh thời đại nào. Các phương pháp tiếp cận như Tăng tốc kỷ nguyên đào tạo các cây bổ sung trên các thời đại mà quần thể hiện tại đang gặp khó khăn. Tuy nhiên, điều này vẫn không xem xét toàn bộ thời đại để dự đoán. Vì mục tiêu chính của các nhà khoa học dữ liệu là xếp hạng các mẫu trong một thời đại nhất định, nên có thể xem xét không chỉ các tính năng mà còn tất cả các mẫu trong một thời đại. Điều này khiến chúng tôi tự hỏi liệu chúng tôi có thể thực hiện được điều gì nếu chúng tôi có thể xem xét tất cả các mẫu trong một thời đại và suy ra điều gì đó từ đó! Các khả năng là Phân cụm thời đại, Tạo thời đại tổng hợp trong một lượt, v.v. Câu hỏi đặt ra là liệu nó có thể cung cấp một số hiểu biết sâu sắc về chuyển động của một nhóm cổ phiếu vì nó có thể nhìn thấy mọi thứ (tất cả) cùng một lúc không?

Tôi đã cố gắng thực hiện những ý tưởng này được một thời gian rồi. Các thử nghiệm ban đầu với LSTM không thành công (có lẽ lúc đó tôi không thể triển khai nó đúng cách). Các thử nghiệm ban đầu của tôi với Transformers coi mỗi hàng là một chuỗi bằng cách nhúng 5 giá trị đầu vào duy nhất {0, 1, 2, 3, 4}. Tuy nhiên, Nó có thể xử lý toàn bộ thời đại cùng một lúc, chỉ bằng cách Chuyển đổi.

Máy biến áp (Era) đến giải cứu

Thay vì coi mỗi hàng là một mẫu, thời đại được đệm thành MAX_LENGTH cố định và do đó được coi là một chuỗi. Các tính năng đã chọn được cung cấp dưới dạng nhúng vào mô hình cùng với mặt nạ tại các vị trí được đệm như trong hình minh họa bên dưới.

Sơ đồ triển khai hiện tại của EraTransformer

def pad_sequence(inputs, padding_value=-1, max_len=None):
    if max_len is None:
        max_len = max([input.shape[0] for input in inputs])
    padded_inputs = []
    masks = []
    for input in inputs:
        pad_len = max_len - input.shape[0]
        padded_input = F.pad(input, (0, 0, 0, pad_len), value=padding_value)
        mask = torch.ones((input.shape[0], 1), dtype=torch.float)
        masks.append(
            torch.cat((mask, torch.zeros((pad_len, 1), dtype=torch.float)), dim=0)
        )
        padded_inputs.append(padded_input)
    return torch.stack(padded_inputs), torch.stack(masks)

def convert_to_torch(era, data):

    inputs = torch.from_numpy(
                data[feature_names].values.astype(np.int8))
    labels = torch.from_numpy(
                data[target_names].values.astype(np.float32))
    
    padded_inputs, masks_inputs = pad_sequence(
            [inputs], padding_value=PADDING_VALUE, max_len=MAX_LEN)
    padded_labels, masks_labels = pad_sequence(
            [labels], padding_value=PADDING_VALUE, max_len=MAX_LEN)

    return {
        era: (
            padded_inputs,
            padded_labels,
            masks_inputs
        )
    }

def get_era2data(df):
    res = Parallel(n_jobs=-1, prefer="threads")(
        delayed(convert_to_torch)(era, data)
        for era, data in tqdm(df.groupby("era_int")))
    era2data = {}
    for r in tqdm(res):
        era2data.update(r)
    return era2data


era2data_train = get_era2data(train)
era2data_validation = get_era2data(validation)
class TransformerEncoder(nn.Module):
    def __init__(
        self,
        input_dim,
        d_model,
        output_dim,
        num_heads,
        num_layers,
        dropout_prob=0.15,
        max_len=5000,
    ):
        super(TransformerEncoder, self).__init__()
        self.input_dim = input_dim
        self.output_dim = output_dim
        self.num_heads = num_heads
        self.num_layers = num_layers
        self.dropout_prob = dropout_prob
        self.d_model = d_model

        self.positional_encoding = PositionalEncoding(d_model, max_len)
        self.attention = MultiHeadLinearAttention(d_model, num_heads)
        self.fc = nn.Sequential(
            nn.Linear(d_model, d_model),
        )
        self.layers = nn.ModuleList(
            [
                nn.Sequential(FeedForwardLayer(d_model=d_model))
                for _ in range(num_layers)
            ]
        )
        self.mapper = nn.Sequential(
            nn.Linear(input_dim, d_model), nn.Linear(d_model, d_model)
        )

    def forward(self, inputs, mask=None):
        x = self.mapper(inputs)
        pe = self.positional_encoding(x)
        x = x + pe # works without PE as well
        for layer in range(self.num_layers):
            attention_weights = self.attention(x, mask)
            x = x + attention_weights
            x = F.layer_norm(x, x.shape[1:])
            x = F.dropout(x, p=self.dropout_prob)

            op = self.layers[layer](x)
            x = x + op
            x = F.layer_norm(x, x.shape[1:])
            x = F.dropout(x, p=self.dropout_prob)

        outputs = self.fc(x)
        return outputs

Sự chú ý của vani quá nặng đối với GPU máy tính xách tay của tôi, vì vậy tôi đã thử sử dụng thứ gì đó như Chú ý tuyến tính vì nó sẽ giảm tải phép nhân ma trận xuống D_MODEL đầu tiên và sau đó là MAX_LEN . Thời gian chạy Colab tiêu chuẩn trong sổ tay được cung cấp sử dụng cơ chế chú ý cố định trên tập hợp con nhỏ các tính năng được cung cấp vì sổ tay này có bộ nhớ GPU cao hơn. Máy tính xách tay có sẵn cả hai dưới dạng thả vào thay thế cho khối chú ý nhiều đầu. Sử dụng bất cứ điều gì làm việc cho bạn.

Kết quả

Các thử nghiệm trong Colab được cung cấp sử dụng tập hợp con tính năng "nhỏ" do giới hạn bộ nhớ. Tuy nhiên, nó sử dụng cơ chế chú ý vanilla. Dưới đây là một mô hình nhỏ được đào tạo trên bộ tính năng nhỏ trong 10 lần lặp lại với tốc độ học tập thấp để tối ưu hóa cho mối tương quan của MSE và Pearson.

Một hàm mất mát sẽ thực thi các phép nhúng trực giao trong đầu ra của bộ mã hóa sẽ có ý nghĩa hơn nhiều đối với việc phân cụm. Việc triển khai hiện tại là một thử nghiệm ban đầu và sẽ trở nên chính xác hơn để triển khai hoàn hảo. Nó dường như đang làm việc mặc dù.

Hiệu suất đào tạo

Hiệu suất trên tập huấn luyện

Hiệu suất xác thực

Hiệu suất trên bộ xác thực

Liên quan đến siêu mô hình

Mối tương quan giữa dự đoán ví dụ và dự đoán siêu mô hình lịch sử

phân cụm

cụm

Cái gì tiếp theo?

  1. Chạy sổ tay Colab (GPU->Chạy tất cả). Tạo một tập tin đệ trình
  2. Mở rộng bộ tính năng (nhỏ -> trung bình -> toàn bộ)
  3. Chơi với cơ chế Chú ý.
  4. Các hàm mất mát để có được các nhúng tốt hơn
  5. Chúng tôi có đầy đủ ý tưởng về dữ liệu trong Tín hiệu; Nó sẽ được áp dụng nhiều hơn ở đó.
  6. Tạo Eras tổng hợp bằng quy trình Khuếch tán
  7. Đào tạo tự giám sát
  • https://github.com/lucidrains/linear-attention-transformer
  • https://numer.ai/data/v4.1
  • Một lần nữa máy tính xách tay Colab
  • ChatGPT + Github Copilot