[PYTHON] Vorhersage des Nikkei-Durchschnitts mit Pytorch 2

Vielen Dank. Neulich habe ich versprochen, mit meinen Junioren in ein öffentliches Bad zu gehen, aber mir wurde verweigert: "Es tut mir leid, ich habe den letzten Zug mit einem Mädchen verpasst ...", und die Arbeit ging mit Wut voran und der Artikel war abgeschlossen.

Also habe ich es im vorherigen Artikel Pytorch Prediction of Nikkei Average ~ Makuma ~ eingeführt.

Using Deep Learning Neural Networks and Candlestick Chart Representation to Predict Stock Market

Ich habe den Datensatz für erstellt, codiert und gelernt, daher werde ich ihn als Memorandum aufbewahren.

Datensatzerstellung

Der hier verwendete Datensatz ähnelt einem Diagramm, ist jedoch etwas Besonderes. (Für Details siehe das Papier !!) Was wurde mit Bezug auf das Papier erstellt 0000.png

Auf diese Weise ist das Bild 48x48 groß und oben und unten werden durch Rot und Grün dargestellt. Unten ist der Code.

candle_make.ipynb


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import csv
import glob
import pandas as pd
import numpy as np
import sys
import matplotlib.pyplot as plt
import datetime
import openpyxl
 
#Kerzenfußdarstellung
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
path = "/content/drive/My Drive/Colab/pytorch_pre/"
sys.path.append("/content/drive/My Drive/Colab/pytorch_pre")
import mpl_finance

Bibliotheksbezogener Import. Da Google Colaboratory verwendet wird, gibt Pfad usw. den Speicherort an, an dem die Dateien auf dem Laufwerk gespeichert sind. Vielleicht ist das seltene mpl_finance. Es kann vom Git Hub heruntergeladen werden. Es ist praktisch, um Kerzenfüße darzustellen. mlp_finance

candle_make.ipynb


future_num = 1
fname = path + "data/nikkei_heikin_x3.csv"
flist = glob.glob(fname)
for file in flist:
  dt = pd.read_csv(file, header=0, encoding="utf-8_sig", index_col='Datetime')

dt = dt.sort_values('Datetime')
print(dt)

future_price = dt.iloc[future_num:-18]['Schlusskurs'].values
curr_price = dt.iloc[:-18-future_num]['Schlusskurs'].values
    
#future_Behandeln Sie den Preis im Vergleich zu Anzahl Tage später als das richtige Etikett
y_data_tmp = future_price / curr_price
#Bereiten Sie eine Liste für das richtige Antwortetikett vor

y_data = np.zeros_like(y_data_tmp)
y_data_nam = np.zeros(len(y_data_tmp)+1, dtype=object)
Y_data = np.zeros((len(y_data_tmp)+1, 2), dtype=object)
Y_columns = ["label","ImageName"]

#Zukunft vorherzusagen_Richtige Antwort, wenn die Anzahl der Tage später steigt
for i in range(len(y_data_tmp)):
    Y_data[i,0] = 0
    if y_data_tmp[i] >= 1.0:
        y_data[i] = 1
        Y_data[i,0] = 1
count = 0
for i in y_data:
  if i == 1:
    count += 1

print(count)
for i in range(1,len(y_data_tmp)+1):
    y_data_nam[i] = "{:04}.png ".format(i-1) 
    Y_data[i,1] = y_data_nam[i]
Y_data[0,0] = "label"
Y_data[0,1] = "ImageName"
dn = pd.DataFrame(Y_data)
dn.columns = Y_columns
np.savetxt(path+"debug/y_data.csv", dn, delimiter=",", fmt='%s') #In CSV-Datei schreiben

Ich werde mich hier um das Etikettieren kümmern. Die gelesenen Daten werden um 1 organisiert und binärisiert, wenn der Preis am Tag höher als am Vortag ist, und um 0, wenn der Preis niedriger als am Vortag ist. Um die Beschriftung später über den Bildnamen aufrufen zu können, ordnen Sie den Dateinamen (Bildname) und die Beschriftung in csv in derselben Zeile an und machen Sie sie wie eine Tabelle.

candle_make.ipynb


img_create = 1
if img_create == 1:
    seq_len = 20
    df = pd.read_csv(fname, parse_dates=True, index_col=0)
    df = df.sort_values('Datetime')
    df = df.rename(columns={'Offener Preis':'Open','Hoher Preis':'High','Niedriger Preis':'Low','Schlusskurs':'Close','Volumen':'Volume'})
    df.fillna(0)
    plt.style.use('dark_background')
    df.reset_index(inplace=True)
    df['Datetime'] = df['Datetime'].map(mdates.date2num)
    for i in range(0, len(df)):
        c = df.iloc[i:i + int(seq_len) - 1, :]
        if len(c) == int(seq_len-1):
            # Date,Open,High,Low,Adj Close,Volume
            ohlc = zip(c['Datetime'], c['Open'], c['High'],
                       c['Low'], c['Close'], c['Volume'])
            my_dpi = 96
            fig = plt.figure(figsize=(48 / my_dpi, 48 / my_dpi), dpi=my_dpi)
            ax1 = plt.subplot2grid((1, 1), (0, 0))
            # candlestick2_ohlc(ax1, c['Open'],c['High'],c['Low'],c['Close'], width=0.4, colorup='#77d879', colordown='#db3f3f')
            mpl_finance.candlestick_ohlc(ax1, ohlc, width=0.4,
                             colorup='#77d879', colordown='#db3f3f')
            ax1.grid(False)
            ax1.set_xticklabels([])
            ax1.set_yticklabels([])
            ax1.xaxis.set_visible(False)
            ax1.yaxis.set_visible(False)
            ax1.axis('off')
#            pngfile = 'datasets/{}_{}_{}.png'.format(
#                i, seq_len, fname[11:-4])
            pngfile = 'datasets/{:04}.png'.format(i)
            fig.savefig(path+pngfile,  pad_inches=0, transparent=False)
            plt.close(fig)
    print("Converting olhc to candlestik finished.")

Dies ist fast das gleiche wie das Papier. Lautstärkeanzeige ist nicht möglich. Bitte lassen Sie mich wissen, wenn Sie können. Da es sich nicht um dieselbe Form von numerischen Daten wie das Papier handelt, wird es abgeglichen. Dies sind die Daten, die ich verwendet habe.

スクリーンショット 2020-09-17 15.51.21.png

Passen Sie die Form durch Umbenennen an. Dies vervollständigt das Bild des Datensatzes.

Lernen

Das Trainingsmodell verwendet ResNet. In der Arbeit wurde SOTA unter Verwendung einer einzigartigen Modellstruktur aufgezeichnet, aber ResNet erzielte auch ausreichende Ergebnisse, sodass ich diese verwenden werde.

resnet.ipynb



class MyDataSet(Dataset):
    def __init__(self, csv_path, root_dir):
        self.train_df = pd.read_csv(csv_path)
        self.root_dir = root_dir
        self.images = os.listdir(self.root_dir)
        self.transform = transforms.Compose([transforms.ToTensor()])
        self.y_columns = ["label","ImageName"]
        
    def __len__(self):
        return len(self.images)
    
    def __getitem__(self, idx):
        #Bild wird geladen
        # print(self.images)
        image_name = self.images[idx]
        image = Image.open(os.path.join(self.root_dir, image_name) )
        image = image.convert('RGB') # PyTorch 0.4 oder später
        # label (0 or 1)
        self.train_df.columns = self.y_columns
        label = self.train_df.query('ImageName=="'+image_name+'"')['label'].iloc[0]
        return self.transform(image), int(label)

def conv3x3(in_channels, out_channels, stride=1, groups=1, dilation=1):
     return nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride,
                      padding=dilation, groups=groups, bias=True,
                      dilation=dilation)


def conv1x1(in_channels, out_channels, stride=1):
     return nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=True)


class BasicBlock(nn.Module):
 #  Implementation of Basic Building Block

    def __init__(self, in_channels, out_channels, stride=1, downsample=None):
     super(BasicBlock, self).__init__()
    
     self.conv1 = conv3x3(in_channels, out_channels, stride)
     self.bn1 = nn.BatchNorm2d(out_channels)
     self.relu = nn.ReLU(inplace=True)
     self.conv2 = conv3x3(out_channels, out_channels)
     self.bn2 = nn.BatchNorm2d(out_channels)
     self.downsample = downsample

    def forward(self, x):
     identity_x = x  # hold input for shortcut connection
    
     out = self.conv1(x)
     out = self.bn1(out)
     out = self.relu(out)
    
     out = self.conv2(out)
     out = self.bn2(out)
    
     if self.downsample is not None:
         identity_x = self.downsample(x)
    
     out += identity_x  # shortcut connection
     return self.relu(out)

class ResidualLayer(nn.Module):

     def __init__(self, num_blocks, in_channels, out_channels, block=BasicBlock):
         super(ResidualLayer, self).__init__()
         downsample = None
         if in_channels != out_channels:
             downsample = nn.Sequential(
                 conv1x1(in_channels, out_channels),
                 nn.BatchNorm2d(out_channels)
         )
         self.first_block = block(in_channels, out_channels, downsample=downsample)
         self.blocks = nn.ModuleList(block(out_channels, out_channels) for _ in range(num_blocks))

     def forward(self, x):
         out = self.first_block(x)
         for block in self.blocks:
             out = block(out)
         return out

class ResNet18(nn.Module):

   def __init__(self, num_classes):
       super(ResNet18, self).__init__()
       self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3)
       self.bn1 = nn.BatchNorm2d(64)
       self.relu = nn.ReLU(inplace=True)
       self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
       self.layer1 = ResidualLayer(2, in_channels=64, out_channels=64)
       self.layer2 = ResidualLayer(2, in_channels=64, out_channels=128)
       self.layer3 = ResidualLayer(
           2, in_channels=128, out_channels=256)
       self.layer4 = ResidualLayer(
           2, in_channels=256, out_channels=512)
       self.avg_pool = nn.AdaptiveAvgPool2d((1, 1))
       self.fc = nn.Linear(512, num_classes)

   def forward(self, x):
       out = self.conv1(x)
       out = self.bn1(out)
       out = self.relu(out)
       out = self.maxpool(out)

       out = self.layer1(out)
       out = self.layer2(out)
       out = self.layer3(out)
       out = self.layer4(out)

       out = self.avg_pool(out)
       out = out.view(out.size(0), -1)
       out = self.fc(out)

       return out
   
class Trainer:

    def __init__(self, model, optimizer, criterion):
        self.device = 'cuda' if torch.cuda.is_available() else 'cpu'
        self.model = model.to(self.device)
        self.optimizer = optimizer
        self.criterion = criterion

    def epoch_train(self, train_loader):
        self.model.train()
        epoch_loss = 0
        correct = 0
        total = 0

        for batch_idx, (inputs, targets) in enumerate(train_loader):
            inputs = inputs.to(self.device)
            targets = targets.to(self.device).long()

            self.optimizer.zero_grad()

            outputs = self.model(inputs)
            loss = self.criterion(outputs, targets)
            loss.backward()
            self.optimizer.step()

            epoch_loss += loss.item()
            _, predicted = torch.max(outputs.data, 1)
            total += targets.size(0)
            correct += predicted.eq(targets.data).cpu().sum().item()

        epoch_loss /= len(train_loader)
        acc = 100 * correct / total
        return epoch_loss, acc

    def epoch_valid(self, valid_loader):
        self.model.eval()
        epoch_loss = 0
        correct = 0
        total = 0

        for batch_idx, (inputs, targets) in enumerate(valid_loader):
            inputs = inputs.to(self.device)
            targets = targets.to(self.device).long()
            outputs = self.model(inputs)
            loss = self.criterion(outputs, targets)

            epoch_loss += loss.item()
            _, predicted = torch.max(outputs.data, 1)
            total += targets.size(0)
            correct += predicted.eq(targets.data).cpu().sum().item()

        epoch_loss /= len(valid_loader)
        acc = 100 * correct / total
        return epoch_loss, acc

    @property
    def params(self):
        return self.model.state_dict()

ResNet-Definition, Lesen von Datensätzen usw. MyDataSet liest die Bezeichnung und den Dateinamen und beschriftet sie.

resnet.ipynb



if __name__ == '__main__':
    model = ResNet18(2)
    
    epoch_n = 100
    
    optimizer = optim.Adam(model.parameters(),
                        lr=0.001,
                        weight_decay=1e-4)
    
    criterion = nn.CrossEntropyLoss()

    trainer = Trainer(model, optimizer, criterion)

    transform = transforms.Compose([
        transforms.Resize((50, 50)),
        transforms.ToTensor(),
    ])

    tmp_data = MyDataSet(path+'debug/y_data.csv', path+'datasets/')
    dtrain, dtest = train_test_split(tmp_data, test_size=0.2)#Sie müssen 4 Ausgänge haben??
    # x_train, y_train, x_test, y_test = train_test_split(tmp_data)
    
    train_loader = torch.utils.data.DataLoader(dtrain, batch_size=43, shuffle=True,
                              drop_last=True)
    valid_loader = torch.utils.data.DataLoader(dtest, batch_size=43, shuffle=True,
                              drop_last=True)
    best_acc = -1
    for epoch in range(1, 1 + epoch_n):
        train_loss, train_acc = trainer.epoch_train(train_loader)
        valid_loss, valid_acc = trainer.epoch_valid(valid_loader)

        if valid_acc > best_acc:
            best_acc = valid_acc
            best_params = trainer.params

        print(f'EPOCH: {epoch} / {epoch_n}')
        print(f'TRAIN LOSS: {train_loss:.3f}, TRAIN ACC: {train_acc:.3f}')
        print(f'VALID LOSS: {valid_loss:.3f}, VALID ACC: {valid_acc:.3f}')

    torch.save(best_params, path + 'models/resnet.pth')

Dies ist der Teil zu lernen. Ich denke, es ist fast das gleiche wie bei einem normalen ResNet. Es ist ein Lernergebnis.

EPOCH: 1 / 100
TRAIN LOSS: 0.700, TRAIN ACC: 62.114
VALID LOSS: 1.145, VALID ACC: 52.442
EPOCH: 2 / 100
TRAIN LOSS: 0.502, TRAIN ACC: 76.391
VALID LOSS: 0.476, VALID ACC: 78.023
EPOCH: 3 / 100
TRAIN LOSS: 0.426, TRAIN ACC: 81.248
VALID LOSS: 0.467, VALID ACC: 77.907
EPOCH: 4 / 100
TRAIN LOSS: 0.368, TRAIN ACC: 83.633
VALID LOSS: 0.357, VALID ACC: 85.000
EPOCH: 5 / 100
TRAIN LOSS: 0.324, TRAIN ACC: 86.488
VALID LOSS: 0.648, VALID ACC: 76.395
EPOCH: 6 / 100
TRAIN LOSS: 0.305, TRAIN ACC: 87.018
VALID LOSS: 0.365, VALID ACC: 84.884
EPOCH: 7 / 100
TRAIN LOSS: 0.277, TRAIN ACC: 88.284
VALID LOSS: 0.480, VALID ACC: 79.884
.
.
.
EPOCH: 92 / 100
TRAIN LOSS: 0.006, TRAIN ACC: 99.853
VALID LOSS: 0.874, VALID ACC: 85.349
EPOCH: 93 / 100
TRAIN LOSS: 0.025, TRAIN ACC: 99.058
VALID LOSS: 0.960, VALID ACC: 78.953
EPOCH: 94 / 100
TRAIN LOSS: 0.028, TRAIN ACC: 99.058
VALID LOSS: 0.992, VALID ACC: 85.698
EPOCH: 95 / 100
TRAIN LOSS: 0.021, TRAIN ACC: 99.264
VALID LOSS: 0.744, VALID ACC: 84.884
EPOCH: 96 / 100
TRAIN LOSS: 0.007, TRAIN ACC: 99.735
VALID LOSS: 1.000, VALID ACC: 85.349
EPOCH: 97 / 100
TRAIN LOSS: 0.008, TRAIN ACC: 99.735
VALID LOSS: 0.834, VALID ACC: 86.279
EPOCH: 98 / 100
TRAIN LOSS: 0.020, TRAIN ACC: 99.470
VALID LOSS: 0.739, VALID ACC: 85.930
EPOCH: 99 / 100
TRAIN LOSS: 0.005, TRAIN ACC: 99.853
VALID LOSS: 0.846, VALID ACC: 86.395
EPOCH: 100 / 100
TRAIN LOSS: 0.016, TRAIN ACC: 99.382
VALID LOSS: 1.104, VALID ACC: 83.953

Die Zugdaten verzeichneten 100% und die Testdaten ebenfalls 87%. Wenn man bedenkt, dass mit dem vorherigen LSTM etwa 60% verwendet werden, ist die Genauigkeit viel besser.

Schlussfolgerung Überlegung

Es stellt sich heraus, dass die Genauigkeit verbessert werden kann, indem Sie einfach oben und unten auf das Bild treffen. Ich weiß nicht, ob es rentabel sein wird, es tatsächlich zu verwenden, aber ... Da dies ein Folgeexperiment zu dem Artikel ist, denke ich darüber nach, Fernunterricht einzubeziehen und von hier aus einen Anstieg von 3% vorherzusagen.

Übrigens stiegen in den Daten von rund 4300 nur 70 gegenüber dem Vortag um 3%. Es ist ein ziemlich unausgeglichener Datensatz, der 5% der Gesamtmenge ausmacht.

Das nächste Mal möchte ich etwas dagegen tun.

Recommended Posts

Vorhersage des Nikkei-Durchschnitts mit Pytorch 2
Vorhersage des Nikkei-Durchschnitts mit Pytorch
Vorhersage des Nikkei-Durchschnitts mit Pytorch ~ Makuma ~
Vorhersage der Sinuswelle mit Keras
Sinuswellenvorhersage (Rückkehr) mit Pytorch
4/22 Vorhersage der Sinuswelle mit Keras
Multi-Class Multi-Label-Klassifizierung von Bildern mit Pytorch
Spiele mit PyTorch
Kreuzvalidierung mit PyTorch
Beginnend mit PyTorch
Verwenden Sie RTX 3090 mit PyTorch
Installieren Sie Fackelstreuung mit PyTorch 1.7
[PyTorch] Ein wenig Verständnis von CrossEntropyLoss mit mathematischen Formeln
Zusammenfassung der Probleme bei der semantischen Segmentierung mit Pytorch
Vorbereiten der Ausführungsumgebung von PyTorch mit Docker November 2019
[PyTorch] Bildklassifizierung von CIFAR-10
Speichern Sie die Ausgabe von GAN nacheinander ~ Mit der Implementierung von GAN durch PyTorch ~
Versuchen Sie Auto Encoder mit Pytorch
Bewegungsgleichung mit Sympy
Implementieren Sie PyTorch + GPU mit Docker
Maschinelles Lernen Minesweeper mit PyTorch
PyTorch mit AWS Lambda [Lambda-Import]
Erinnerungen an den Kampf mit Selen
Schaben Nikkei Durchschnitt mit Dramatiker-Python
Führen Sie mit PyTorch eine geschichtete Aufteilung durch
Ich habe Word2Vec mit Pytorch gemacht
Wahrscheinlichkeitsvorhersage von unausgeglichenen Daten
Fehlerfreie Berechnung mit Golangs big.Float
Einfache Vorhersage von Zeitreihen mit Prophet
Rastersuche von Hyperparametern mit Scikit-learn
Beurteilung von Feiertagen einschließlich Feiertagen mit Bash
[PyTorch Tutorial ⑤] PyTorch anhand von Beispielen lernen (Teil 2)
Zusammenfassung der grundlegenden Implementierung von PyTorch
Lernen Sie mit PyTorch Graph Convolutional Networks
Versuchen Sie, Pferderennen mit Chainer vorherzusagen
Ich habe versucht, Attention Seq2Seq mit PyTorch zu implementieren
Erste Schritte mit Python Grundlagen von Python
Ich habe versucht, DeepPose mit PyTorch zu implementieren
Lebensspiel mit Python! (Conways Spiel des Lebens)
Automatisierung von Remote-Operationen mit Fabric
10 Funktionen von "Sprache mit Batterie" Python
Aufblasen von Daten (Datenerweiterung) mit PyTorch
4. Nacht der Schleife mit für
Grundlagen zum Berühren von MongoDB mit MongoEngine
[PyTorch Tutorial ⑤] PyTorch anhand von Beispielen lernen (Teil 1)
Angemessene japanische Übersetzung von pytorch tensor_tutorial
Implementierung der Dyxtra-Methode durch Python
pytorch @ python3.8 Umgebungskonstruktion mit pipenv
Koexistenz von Python2 und 3 mit CircleCI (1.0)
Erzielen Sie mit Tensorflow eine Pytorch-Reflexionspolsterung
Plotten Anwenden von Diagrammen mit Schiebereglern
Grundlegendes Studium von OpenCV mit Python
Eine Sammlung von Tipps zur Beschleunigung des Lernens und Denkens mit PyTorch