# -*- coding:utf-8 -*-
import sys
import numpy as np
import pandas as pd
import os
n_gram = int(sys.argv[1])
print("n = ", n_gram)
kind_pth = r"F:\my_project\apk_sample\kind"
cntKind = len(os.listdir(kind_pth))

def sigmoid(z):
    return 1.0 / (1.0 + np.exp(-z))


def dsigmoid(z):
    return sigmoid(z) * (1.0 - sigmoid(z))


def data_process(dataPath):
    global xTrain, yTrain
    xFrame = pd.read_csv(dataPath, usecols=np.arange(0,7**n_gram).tolist())
    yFrame = pd.read_csv(dataPath, usecols=[7**n_gram])
    xTrain = np.array(xFrame).astype(int)
    yTrain = np.array(yFrame).astype(int)
    # print(yTrain.shape)  # (222, 1)
    return xTrain, yTrain


def logistics_regression(xTrain, yTrain):
    weight = np.zeros(len(xTrain[0]))
    # print(weight)
    bias = 0.0
    learning_rate = 0.0001
    epochs = 1000
    w_sum = np.zeros(len(xTrain[0]))
    b_sum = 0.0

    for i in range(epochs):
        # 记录一次迭代的梯度总和
        w_grad = np.zeros(len(xTrain[0]))
        b_grad = 0.0
        for j in range(len(xTrain)):
            w_grad += (-xTrain[j]).T * (yTrain[j]-sigmoid(xTrain[j].T.dot(weight)+bias))
            b_grad += (-1) * (yTrain[j]-sigmoid(xTrain[j].T.dot(weight)+bias))
        w_grad /= len(xTrain)
        b_grad /= len(xTrain)
        # adagad
        w_sum += w_grad ** 2
        b_sum += b_grad ** 2
        # gradient descent
        weight -= learning_rate/np.sqrt(w_sum) * w_grad
        bias -= learning_rate/np.sqrt(b_sum) * b_grad
    # print(weight)
    # print(bias)
    return weight, bias


def test_model(weight, bias):
    # show the weight and bias
    # print(weight)
    # print(bias)
    # test model
    res = []
    for i in range(len(xTrain)):
        # output from the model
        tmp = xTrain[i].T.dot(weight) + bias
        if sigmoid(tmp) >= 0.5:
            res.append(1)
        else:
            res.append(0)
    sumOfKind, sumOfVirus = 0., 0.
    for i in range(cntKind):
        if res[i] == yTrain[i]:
            sumOfKind += 1
    for i in np.arange(cntKind, len(yTrain)):
        if res[i] == yTrain[i]:
            sumOfVirus += 1
    print('accuracy in testing data')
    print('accuracy in kind sample: %.3f' % (100 * sumOfKind / cntKind) + '%')
    # print(len(yTrain))  # 由于加壳会导致反编译失败，因此实际得到的样本数量小于收集的
    print('accuracy in virus sample: %.3f' % (100 * sumOfVirus / (len(yTrain)-cntKind)) + '%')


def main():
    dataPath = str(n_gram)+'_gram.csv'
    x, y = data_process(dataPath)
    weight, bias = logistics_regression(x, y)
    test_model(weight, bias)


if __name__ == '__main__':
    main()
