Erkennung der Chiralität eines Proteins durch ein Neuronales Netzwerk

Chiralität in der Proteinfaltung

In der Proteinfaltung gibt es zu jedem Protein auch eine gespiegelte Form. Bisher ist es schwierig zu sagen, ob ein Protein in der gespiegelten Form vorliegt.

In diesem Artikel beschreiben wir einen Weg, wie die Chiralität eines Proteins durch ein Neuronales Netzwerk mit Tensorflow bestimmt werden kann.

Unser Verfahren

Das gesamte Verfahren wird hier vollständig beschrieben, damit jeder es nachmachen und weiter verbessern kann. Dieses Verfahren ist eine vollständig eigene Entwicklung von Kroll-Software und basiert auf keinen anderen Ideen. Bitte zitieren sie uns, wenn Sie dieses Verfahren verwenden.

Das Verfahren macht eine Voraussage über die Chiralität eines Proteins.

Motivation

Wenn ein Protein durch einen Algorithmus gefaltet wird, kann es oft geschehen, dass es falsch herum gefaltet wird. Daher ist es wichtig, seine Chiralität zu erkennen, um es zu spiegeln, wenn dies erforderlich ist.

Daten

Die verwendeten Trainings-Daten stammen aus der öffentlich zugänglichen Protein Datenbank (PDB).

Implementierung

Das Neuronale Netzwerk nutzt Keras / Tensorflow (oder ein anderes Backend). Wir programmieren in C# und verwenden eine modifizierte Version von Keras.NET. Alle Codebeispiele sind daher in C#, lassen sich aber leicht in andere Sprachen adaptieren.

Netzwerk Architektur / Topologie

chirality-model

BaseModel BuildModel()
{
    bool useBias = false;
    string initializer = "random_uniform";

    Sequential model = new Sequential();
    model.Add(new Dense(units: 720, input_dim: 720));

    model.Add(new Dense(units: 720, activation: "tanh", use_bias: useBias, kernel_initializer: initializer));
    model.Add(new Dense(units: 720, activation: "tanh", use_bias: useBias, kernel_initializer: initializer));

    model.Add(new LeakyReLU());
    model.Add(new Dense(units: 540, use_bias: useBias, kernel_initializer: initializer));

    model.Add(new LeakyReLU());
    model.Add(new Dense(units: 540, use_bias: useBias, kernel_initializer: initializer));

    model.Add(new LeakyReLU());
    model.Add(new Dense(units: 320, use_bias: useBias, kernel_initializer: initializer));

    model.Add(new Dense(units: 2, activation: "softmax"));
    
    var optimizer = new Adam(lr: 0.25e-5f);
    model.Compile(optimizer: optimizer,
        loss: "categorical_crossentropy",
        metrics: new string[] { "accuracy" });

    model.Summary();
    model.Plot("chirality-model.png");

    return model;
}

Eingabewerte

Das Modell erhält alle Winkel Phi und Psi der Alphakette des Proteins in einem vektorisierten Array.

Vektorisierungs-Funktion


float[] Vectorize(double[] Phi, double[] Psi, bool randomize = false)
{
    float[] arr = new float[720];

    foreach (double d in Phi)
    {
        double degree = d.ToDegree();
        int idx = (int)(degree + 180.5);

        while (idx < 0)
            idx += 360;
        while (idx >= 360)
            idx -= 360;

        if (randomize)
            RandomizeIndex(idx);

        arr[idx] += 1;
    }

    foreach (double d in Psi)
    {
        double degree = d.ToDegree();
        int idx = (int)(degree + 180.5);

        while (idx < 0)
            idx += 360;
        while (idx >= 360)
            idx -= 360;

        if (randomize)
            RandomizeIndex(idx);

        arr[idx + 360] += 1;
    }

    if (randomize)
        AddNoise(arr, Phi.Length / 10);

    // Normalize
    float max = arr.Max();
    for (int j = 0; j < 720; j++)
        arr[j] /= max;

    return arr;
}

Randomisierung

Wir randomisieren den Eingabevektor für grössere Robustheit.


int RandomizeIndex(int idx)
{
    const int range = 45;
    int r = ThreadSafeRandom.Next(range);
    if (ThreadSafeRandom.NextDouble() < 0.5)
        r = -r;

    int ret = idx + r;
    while (ret < 0)
        ret += 360;
    while (ret >= 360)
        ret -= 360;

    return ret;
}

Rauschen

Wir fügen auch etwas Rauschen hinzu.


float[] AddNoise(float[] vec, int count)
{
    int half = vec.Length / 2;

    for (int i = 0; i < count; i++)
    {
        int idx = ThreadSafeRandom.Next(360);
        vec[idx] += 1;
    }

    for (int i = 0; i < count; i++)
    {
        int idx = ThreadSafeRandom.Next(360);
        vec[idx + half] += 1;
    }

    return vec;
}

Training

Dies ist unsere Trainingsfunktion in Keras.NET / C#


public double[] BatchTrain(List data, bool evaluate = false, bool randomize = false)
{
    int batch_size = 32;
    int batchStart = 0;

    if (evaluate)
        batch_size = data.Count;

    List retLoss = new List();
    List retErr = new List();

    MRE.Reset();
    var ts = PythonEngine.BeginAllowThreads();

    try
    {
        while (batchStart < data.Count)
        {
            int count = Math.Min(batch_size, data.Count - batchStart);

            float[,] chirlist = new float[count, 720];
            float[,] yval = new float[count, 2];

            for (int j = 0; j < count; j++)
            {
                ChiralityData chir = data[j + batchStart];

                float[] vec = Vectorize(chir.Phi, chir.Psi, randomize);
                for (int k = 0; k < 720; k++)
                {
                    chirlist[j, k] = vec[k];
                }

                yval[j, 0] = chir.Mirrored ? 0 : 1;
                yval[j, 1] = chir.Mirrored ? 1 : 0;
            }

            using (Py.GIL())
            {
                var train = new NDarray(chirlist);
                var y = new NDarray(yval);

                double[] retVal = null;

                if (evaluate)                        
                    retVal = Model.Evaluate(train, y, verbose: 0);                        
                else                        
                    retVal = Model.TrainOnBatch(train, y);

                retLoss.Add(retVal[0]);
                retErr.Add(retVal[1]);
            }

            batchStart += batch_size;
        }
    }
    catch (Exception ex)
    {
        ex.LogError();
        HasErrors = true;
    }
    finally
    {
        PythonEngine.EndAllowThreads(ts);
        MRE.Set();
    }

    double lossVal = retLoss.Sum() / retLoss.Count;
    double errVal = retErr.Sum() / retErr.Count;

    return new double[] { lossVal, errVal };
}

Credits

Citation needed.

Unterstützen Sie diese Forschung

Wenn Ihnen diese Forschung gefällt, freuen wir uns auf Ihre Unterstützung. Bitte kontaktieren Sie uns.