机器学习简单小总结 解决糖尿病分类问题和sin函数回归问题

本文探讨了一组糖尿病数据集的分析,发现糖尿病患者某些属性值普遍高于正常人。接着,通过BP神经网络、SVM和支持向量机进行分类任务,以及BP神经网络进行回归任务。在训练和测试集上,SVM表现出最佳的分类性能,其次是BP神经网络,朴素贝叶斯分类器表现最弱。此外,过拟合现象在BP神经网络中被观察到。所有模型的AUC值均超过0.8,表明它们在区分糖尿病患者和非患者方面有一定的准确性。
摘要由CSDN通过智能技术生成

记录

数据分析

分类任务

数据信息

数据条数标签为1标签为0数据维度
5761973798

数据分析
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

由图像可分析,糖尿病患者其属性大部分都略高于正常人,1、2、8属性尤为明显
3、4,、5属性与正常人差异几乎没有。

回归任务

在这里插入图片描述

5000个数据点,由图像可知显然是一个正弦函数回归数据

BP分类任务

  • 结构 使用三层Linear神经网络,使用 σ ( x ) \sigma(x) σ(x)激活函数,均方差损失函数
    σ ( x ) = 1 1 + e − x E l o s s = 1 n ∑ i = 1 n ( y ^ − y ) 2 \sigma(x) = \frac{1}{1+e^{-x}} \qquad E_{loss}=\frac{1}{n}\sum_{i=1}^n(\hat{y}-y)^2 σ(x)=1+ex1Eloss=n1i=1n(y^y)2

  • 参数 每层的参数为(8,8),(8,5),(5,1),学习率0.02,迭代次数10000次

  • 测试结果


    训练loss变化情况如下:
    在这里插入图片描述

大致看出在训练20个左右单位圈数时得到最佳效果,在之后发生过拟合现象。(一个单位是100epoch)


迭代10000次后,在576个样本的训练集中,482 个数据分类正确,准确率0.837,在192个样本的测试集中144个数据分类正确,准确率0.75,显然发生过拟合。


在训练过程中产生的最佳效果(未发生过拟合时)192个测试集中,156个数据分类正确,准确率0.8125

结果

混淆矩阵(尚未过拟合时的最好效果)
真实情况 预测结果
正例反例
正例36(TP)30(FN)
反例6(FP)120(TN)

查准率 P = 0.857 P=0.857 P=0.857
查全率 R = 0.545 R=0.545 R=0.545
在这里插入图片描述

AUC 为 0.8541366041366042

SVM分类任务

  • 结构 使用核函数和软间隔加持的支持向量机

  • 参数 使用线性核函数 , C = 3000 C=3000 C=3000的软间隔惩罚,10次

  • 测试结构在576个训练集中,432个数据分类成功,准确率0.75,192个测试集中,150个数据分类正确,准确率0.78125

混淆矩阵
真实情况 预测结果
正例反例
正例49(TP)17(FN)
反例25(FP)101(TN)

查准率 P = 0.662 P=0.662 P=0.662
查全率 R = 0.742 R=0.742 R=0.742
在这里插入图片描述

AUC is : 0.8733766233766234

beyesian分类任务

  • 结构 使用高斯分布的朴素贝叶斯分类器

  • 参数 没有任何参数,直接统计也不需要迭代

  • 测试结构在576个训练集中,434个数据分类成功,准确率0.7535,在192个测试集中,151个数据分类正确,准确率0.7865

混淆矩阵
真实情况 预测结果
正例反例
正例41(TP)25(FN)
反例16(FP)110(TN)

查准率 P = 0.719 P=0.719 P=0.719
查全率 R = 0.621 R=0.621 R=0.621
在这里插入图片描述

AUC is : 0.8464405964405965

BP回归任务

  • 结构 使用两层Linear神经网络,使用 σ ( x ) \sigma(x) σ(x)激活函数,均方差损失函数
    σ ( x ) = 1 1 + e − x E l o s s = 1 n ∑ i = 1 n ( y ^ − y ) 2 \sigma(x) = \frac{1}{1+e^{-x}} \qquad E_{loss}=\frac{1}{n}\sum_{i=1}^n(\hat{y}-y)^2 σ(x)=1+ex1Eloss=n1i=1n(y^y)2

  • 参数 每层的参数为(1,15),(15,1),学习率0.0015,迭代次数14000次

  • 测试结果


    训练loss变化图
    在这里插入图片描述


测试集对比结果

在这里插入图片描述

线性回归

分析数据可知,该问题很难直接使用线性回归问题,也无法使用广义线性回归求解。
y = w x + b y=wx+b y=wx+b
先对数据中的x先升维处理(暂且不易引入核函数升维)。

数据本身为1维度,暂把数据升维4维数据,升维方式如:
( x ) i → ( x 2 , x 4 , x 6 , x 8 ) i (x)_i\rightarrow(x^2,x^4,x^6,x^8)_i (x)i(x2,x4,x6,x8)i
再安装多元线性回归求解
W = ( X T X ) − 1 X T Y W=(X^TX)^{-1}X^TY W=(XTX)1XTY
在这里插入图片描述

在这里插入图片描述

小结

支持向量机分类器朴素贝叶斯分类器BP神经网络分类器
训练集0.7500.7540.781
测试集0.7820.7870.813
AUC0.8730.8460.854

在这里插入图片描述

相关代码

读入数据及其分析

import numpy as np


def getClassificationData(str):
    f = open(str, 'r')
    lines = f.readlines()
    f.close()
    dataSet = []
    Label = []
    for line in lines:
        s = line.split()
        data = [float(ch) for ch in s]
        Label.append([int(data[0])])
        data = data[1:]
        dataSet.append(data)
    return map(np.array, (dataSet, Label))


def getRegressionData(str):
    f = open(str, 'r')
    lines = f.readlines()
    f.close()
    dataSet = []
    Label = []
    for line in lines:
        s = line.split()
        dataSet.append([float(s[1])])
        Label.append([float(s[0])])
    return map(np.array, (dataSet, Label))


def viewRegressionData():
    data, Label = getRegressionData('regression/sinc_train')
    plt.plot(data.reshape(-1), Label.reshape(-1), 'o')
    plt.show()


def analyseClassificationData():
    data, Label = getClassificationData('classification/diabetes_train')
    data_a = []
    data_b = []
    for da, la in zip(data, Label):
        if la == 1:
            data_a.append(da)
        else:
            data_b.append(da)
    print("1:", len(data_a), "0:", len(data_b))
    data_a = np.array(data_a)
    data_b = np.array(data_b)
    for i in range(8):
        plt.subplot(1, 2, 1)
        plt.hist([data_a[:, i], data_b[:, i]], bins=20, range=[0, 1], density=True, cumulative=False)
        plt.title("histogram of attribute" + str(i+1))
        plt.subplot(1, 2, 2)
        plt.hist([data_a[:, i], data_b[:, i]], bins=20, range=[0, 1], density=True, cumulative=True)
        plt.title("cumulative of attribute" + str(i+1))
        plt.savefig("fig"+str(i+1))
        plt.show()

朴素贝叶斯分类器

import numpy as np
import ReadData

def Norm_distribute(x, sigma, mean):
    return 1 / ((2 * np.pi) ** 0.5 * sigma) * np.exp(-(x - mean) ** 2 / (2 * sigma ** 2))


class Beyesian_continue:
    def __init__(self, dataSet, label):
        dic = {}
        for la in label:
            if dic.__contains__(la) is False:
                dic[la] = 0
            dic[la] = dic[la] + 1
        lable_kind = len(dic.keys())
        dim = len(dataSet[0])
        totNum = len(dataSet)

        self.dim = dim
        self.C_num = lable_kind
        self.PC = np.zeros(lable_kind)
        self.EX = np.zeros([self.C_num, self.dim])
        self.sig = np.zeros([self.C_num, self.dim])
        for c in range(self.C_num):
            if dic.__contains__(c):
                self.PC[c] = dic[c] / totNum

        for u in range(totNum):
            for d in range(dim):
                self.EX[label[u], d] = self.EX[label[u], d] + dataSet[u, d]
                self.sig[label[u], d] = self.sig[label[u], d] + dataSet[u, d] ** 2

        for c in range(self.C_num):
            for d in range(dim):
                self.EX[c, d] = self.EX[c, d] / dic[c]
                self.sig[c, d] = (self.sig[c, d] / dic[c] - self.EX[c, d] ** 2) ** 0.5

    def predict(self, x):
        t = []
        for c in range(self.C_num):
            p = self.PC[c]
            for d in range(self.dim):
                p = p * Norm_distribute(x[d], self.sig[c, d], self.EX[c, d])
            t.append(p)
        return np.argmax(t)

    def __call__(self, *args, **kwargs):
        return self.predict(*args)


train_x, train_y = ReadData.getClassificationData('classification/diabetes_train')
test_x, test_y = ReadData.getClassificationData('classification/diabetes_test')
beyes = Beyesian_continue(train_x, train_y.reshape(-1))

ans = 0
for (tx, ty) in zip(train_x, train_y):
    ans = ans + (beyes(tx) == ty)[0]
print(ans, ans / len(train_x))

ans = 0
TP = 0
TN = 0
FN = 0
FP = 0
for (tx, ty) in zip(test_x, test_y):
    haty = beyes(tx)
    ans = ans + (haty == ty)[0]
    TP = TP + (haty == 1) * (ty == 1)[0]
    TN = TN + (haty == 0) * (ty == 0)[0]
    FN = FN + (haty == 0) * (ty == 1)[0]
    FP = FP + (haty == 1) * (ty == 0)[0]
print(ans, ans / len(test_x))

print('TP\tFN\t[', TP, ' ', FN, ']')
print('FP\tTN\t[', FP, ' ', TN, ']')
print('P =', TP / (TP + FP), ' R=', TP / (TP + FN))
Ttot = np.sum(test_y == 1)
Ftot = np.sum(test_y == 0)

point = np.array([[beyes.getP(test_x[i], 1), test_y[i][0]] for i in range(len(test_x))])

l = len(point)
for i in range(l):
    j = np.argmax(point[i:, 0]) + i
    t = point[i].copy()
    point[i] = point[j]
    point[j] = t

cnt_T = 0
TPR = []
FPR = []
for i in range(l):
    cnt_T = cnt_T + point[i][1]
    TPR.append(cnt_T / Ttot)
    FPR.append((i - cnt_T + 1) / Ftot)
TPR = np.array(TPR)
FPR = np.array(FPR)

plt.plot(FPR, TPR)
font = FontProperties(fname=r"C:\Windows\Fonts\simhei.ttf", size=14)
plt.title('贝叶斯分类器 ROC曲线', fontproperties=font)
plt.xlabel("假正例率", fontproperties=font)
plt.ylabel("真正例率", fontproperties=font)
print('AUC is :', np.sum((TPR[1:] + TPR[:-1]) * 0.5 * (FPR[1:] - FPR[:-1])))
plt.show()

支持向量机分类器

import numpy as np
import matplotlib.pyplot as plt
from ML import ReadData
from matplotlib.font_manager import FontProperties

class SVM:
    def __init__(self, dim, kennel=None, Name='svm'):
        self.dim = dim
        self.w = np.zeros([1, dim])
        self.b = np.zeros([1, 1])
        self.kennel = kennel
        self.LamAndY = np.zeros([1, 1])
        self.data = np.zeros([1, 1])
        self.Name = Name

    def train(self, x, y, epochs=20, callback=None, Lam=None, C_val=np.inf, Log=True):
        N = len(x)
        Mat_dot = np.zeros([N, N])
        Mat_dot_y = np.zeros([N, N])
        for i in range(N):
            for j in range(N):
                if self.kennel is None:
                    Mat_dot[i, j] = np.dot(x[i], x[j])
                else:
                    Mat_dot[i, j] = self.kennel(x[i], x[j])
                Mat_dot_y[i, j] = Mat_dot[i, j] * y[i] * y[j]
        if Lam is None:
            Lam = np.random.rand(N)
            delta = np.dot(Lam, y)
            for i in range(N):
                if delta * y[i] < 0:
                    Lam[i] = Lam[i] - y[i] * delta
                    delta = 0
                    if Lam[i] > C_val:
                        delta = (Lam[i] - C_val) * y[i]
                        Lam[i] = C_val
        if Log:
            print('初始化完毕')
        for epoch in range(epochs):
            for a in range(N):
                for b in range(N):
                    subb = Mat_dot[a, a] - Mat_dot[b, a] * 2 + Mat_dot[b, b]
                    if subb == 0:
                        continue

                    C = - Lam[a] * y[a] - Lam[b] * y[b]
                    Sum_Lam_a = np.dot(Lam, Mat_dot_y[:, a]) - Lam[a] * Mat_dot_y[a, a] - Lam[b] * Mat_dot_y[b, a]
                    Sum_Lam_b = np.dot(Lam, Mat_dot_y[:, b]) - Lam[a] * Mat_dot_y[a, b] - Lam[b] * Mat_dot_y[b, b]

                    suba = y[a] * C * (Mat_dot[a, b] - Mat_dot[b, b]) + 1 - y[a] * y[b] - Sum_Lam_a + y[a] * \
                           y[b] * Sum_Lam_b

                    U = suba / subb
                    V = -(C + U * y[a]) * y[b]
                    rate = 1
                    if U < 0:
                        rate = min(rate, (0 - Lam[a]) / (U - Lam[a]))
                    if V < 0:
                        rate = min(rate, (0 - Lam[b]) / (V - Lam[b]))
                    if U > C_val:
                        rate = min(rate, (C_val - Lam[a]) / (U - Lam[a]))
                    if V > C_val:
                        rate = min(rate, (C_val - Lam[b]) / (V - Lam[b]))
                    Lam[a] = Lam[a] + (U - Lam[a]) * rate
                    Lam[b] = Lam[b] + (V - Lam[b]) * rate
            if callback is not None:
                callback(x, y, Lam, self.dim, self.kennel)
        if self.kennel is None:
            w = np.zeros([1, self.dim])
            for i in range(N):
                w = w + Lam[i] * y[i] * x[i]
            h = []
            for i in range(N):
                if Lam[i] > 1e-9:
                    h.append(np.dot(w, x[i]))
            h = np.array(h)
            self.w = w
            self.b[0][0] = (np.max(h) + np.min(h)) / 2
        else:
            self.LamAndY = []
            for i in range(N):
                self.LamAndY.append(Lam[i] * y[i])
            self.data = x
            h = []
            for i in range(N):
                if Lam[i] < 1e-9:
                    continue
                res = 0
                for lay, vec in zip(self.LamAndY, self.data):
                    res = res - lay * self.kennel(vec, self.data[i])
                h.append(res)
            h = np.array(h)
            self.b = (np.max(h) + np.min(h)) / 2
        if Log:
            print('训练结束')
        return Lam

    def forward(self, x):
        if self.kennel is None:
            return self.w @ x.T + self.b
        else:
            ret = np.zeros([1, len(x)])
            for lay, vec in zip(self.LamAndY, self.data):
                ret = ret + lay * self.kennel(vec, x)
            return ret + self.b

    def save(self):
        np.save('save/' + self.Name + '_LamAndY', np.array(self.LamAndY))
        np.save('save/' + self.Name + '_w', np.array(self.w))
        np.save('save/' + self.Name + '_b', np.array(self.b))

    def load(self, data=None):
        try:
            self.LamAndY = np.load('save/' + self.Name + '_LamAndY.npy')
            self.w = np.load('save/' + self.Name + '_w.npy')
            self.b = np.load('save/' + self.Name + '_b.npy')
        finally:
            self.data = data

    def __call__(self, *args, **kwargs):
        return self.forward(*args)


class TestSVM:
    def __init__(self, N=50):
        x = np.random.rand(N, 2)
        x[:, 1] = x[:, 1] * 2
        y = ((x[:, 0] * 3 - 1) > x[:, 1]) * 2 - 1
        for i in range(len(x)):
            if y[i] < 0:
                x[i][1] = x[i][1] - 0.5
        # y = (np.random.rand(N) > 0.5) * 2 - 1
        self.x = x
        self.y = y
        self.point_x = []
        self.point_y = []
        for a, b in zip(x, y):
            if b == 1:
                self.point_x.append(a.tolist())
            else:
                self.point_y.append(a.tolist())
        self.point_x, self.point_y = map(np.array, (self.point_x, self.point_y))
        self.svm = SVM(2, kennel=self.kennel, Name='small_svm')

    def kennel(self, x, y):
        if len(x.shape) == 1 and len(y.shape) == 1:
            return np.dot(x, y)
        return np.dot(x.reshape([1, -1]), y.T)

    def test(self, train=True):
        plt.ion()
        if train:
            self.svm.train(self.x, self.y, 30, self.callback, C_val=1000)
        conlose = (self.svm(self.x) > 0) * 2 - 1
        print(conlose, self.y)
        print(np.sum(conlose == self.y), '/', len(self.x))
        plt.ioff()

    def callback(self, x, y, Lam, dim, kennel):
        w = np.zeros([1, dim])
        for i in range(len(x)):
            w = w + Lam[i] * y[i] * x[i]

        h = []
        for i in range(len(x)):
            if Lam[i] < 1e-9:
                continue
            res = 0

            for la_, y_, vec in zip(Lam, y, x):
                res = res - la_ * y_ * kennel(vec, x[i])
            h.append(res)
        h = np.array(h)
        b = (np.max(h) + np.min(h)) / 2
        lx = np.arange(0, 1, 0.01)
        ly = -(w[0][0] * lx + b) / w[0][1]
        plt.cla()
        plt.plot(self.point_x[:, 0], self.point_x[:, 1], 'o')
        plt.plot(self.point_y[:, 0], self.point_y[:, 1], 'o')
        plt.plot(lx, ly)
        plt.pause(0.05)
        cal = np.sum(Lam)

        for i in range(len(x)):
            for j in range(len(x)):
                cal = cal - 0.5 * Lam[i] * Lam[j] * y[i] * y[j] * np.dot(x[i], x[j])
        print(cal, w, b)


class TestSVM_Classification:
    def __init__(self, TestNum=1000, ):
        self.train_x, self.train_y = ReadData.getClassificationData('classification/diabetes_train')
        self.test_x, self.test_y = ReadData.getClassificationData('classification/diabetes_test')
        self.train_y = self.train_y * 2 - 1
        self.test_y = self.test_y * 2 - 1
        if TestNum < len(self.test_x):
            self.train_x = self.train_x[:TestNum, ]
            self.train_y = self.train_y[:TestNum, ]
        self.svm = SVM(len(self.train_x[0]),kennel=self.linearKennel, Name='svm_Classification')
        self.gamma = 1
        self.Lam = np.zeros([1, len(self.train_x)])

    def train(self, epochs=20, C=1e9):  # 训练模型
        self.Lam = self.svm.train(self.train_x, self.train_y, epochs=epochs, callback=self.callback, C_val=C)
        print(np.sum((self.svm(self.train_x) > 0) * 2 - 1 == self.train_y.T), len(self.train_x))

    def trainAgain(self, epochs=20, C=1e9, log=False):  # 在原理基础上继续训练
        self.svm.train(self.train_x, self.train_y, epochs=epochs, callback=self.callback, Lam=self.Lam, C_val=C,
                       Log=log)
        right = np.sum((self.svm(self.train_x) > 0) * 2 - 1 == self.train_y.T)
        print(right, right / len(self.train_x))

    def test(self):  # 用测试集测试模型
        self.svm.data = self.train_x
        hhy = self.svm(self.test_x)
        haty = (hhy > 0) * 2 - 1
        print(haty)
        print(self.test_y.T)
        TP = np.sum((haty == 1) * (self.test_y.T == 1))
        TN = np.sum((haty == -1) * (self.test_y.T == -1))
        FN = np.sum((haty == -1) * (self.test_y.T == 1))
        FP = np.sum((haty == 1) * (self.test_y.T == -1))
        print((TP + TN), (TP + TN) / len(self.test_x))
        print('TP\tFN\t[', TP, ' ', FN, ']')
        print('FP\tTN\t[', FP, ' ', TN, ']')
        print('P =', TP / (TP + FP), ' R=', TP / (TP + FN))
        print("F1=",2*TP/(TP-TN+len(self.svm.data)))
        Ttot = np.sum(self.test_y == 1)
        Ftot = np.sum(self.test_y == -1)
        point = np.array([[p[0], y[0]] for p, y in zip(hhy.T, self.test_y)])
        l = len(point)
        for i in range(l):
            j = np.argmax(point[i:, 0]) + i
            t = point[i].copy()
            point[i] = point[j]
            point[j] = t
        cnt_T = 0
        TPR = []
        FPR = []
        for i in range(l):
            cnt_T = cnt_T + (point[i][1] == 1) * 1
            TPR.append(cnt_T / Ttot)
            FPR.append((i - cnt_T + 1) / Ftot)
        TPR = np.array(TPR)
        FPR = np.array(FPR)
        plt.plot(FPR, TPR)
        font = FontProperties(fname=r"C:\Windows\Fonts\simhei.ttf", size=14)
        plt.title('SVM的ROC曲线', fontproperties=font)
        plt.xlabel("假正例率", fontproperties=font)
        plt.ylabel("真正例率", fontproperties=font)
        print('AUC is :', np.sum((TPR[1:] + TPR[:-1]) * 0.5 * (FPR[1:] - FPR[:-1])))
        plt.show()
        return FPR, TPR

    def save(self):  # 保存模型
        np.save('save/' + self.svm.Name + '_Lam.npy', self.Lam)
        self.svm.save()

    def load(self):  # 重载模型
        self.svm.load()
        self.Lam = np.load('save/' + self.svm.Name + '_Lam.npy')

    def kennel(self, x, y):  # 高斯核函数
        if len(x.shape) == 1 and len(y.shape) == 1:
            return np.exp(-np.dot(x - y, x - y) / (2 * self.gamma ** 2))
        return np.exp(- np.sum((x - y) ** 2, axis=1) / (2 * self.gamma ** 2))

    def linearKennel(self, x, y):
        if len(x.shape) == 1 and len(y.shape) == 1:
            return np.dot(x, y)
        return np.dot(x.reshape([1, -1]), y.T)

    def callback(self, x, y, Lam, dim, kennel):  # 回调函数
        cal = np.sum(Lam)
        for i in range(len(x)):
            for j in range(len(x)):
                cal = cal - 0.5 * Lam[i] * Lam[j] * y[i] * y[j] * np.dot(x[i], x[j])
        print(cal)

#测试的小例子
#test = TestSVM(30)
#test.test()

csvm = TestSVM_Classification()
csvm.train(5, 2100)
csvm.test()

BP神经网络分类器

import matplotlib.pyplot as plt
import numpy as np
import ReadData
from matplotlib.font_manager import FontProperties


class Sigmoid:
    def __call__(self, x):
        return 1 / (1 + np.exp(-x))

    def grad(self, d):
        return d * (1 - d)


class Linear:
    def __init__(self, in_size, out_size, Func=Sigmoid(), lr=0.02, Name='BpNet'):
        self.Name = Name
        self.weight = np.random.rand(in_size, out_size)  # shape=(in_size,out_size)
        self.bias = np.random.rand(1, out_size)  # shape = (1,out_size)
        self.data_in = []
        self.data_out = []
        self.Func = Func
        self.lr = lr

    def save(self):
        np.save('save/' + self.Name + '_weight', np.array(self.weight))
        np.save('save/' + self.Name + '_bias', np.array(self.bias))

    def load(self):
        self.weight = np.load('save/' + self.Name + '_weight.npy')
        self.bias = np.load('save/' + self.Name + '_bias.npy')

    def forward(self, x):
        self.data_in = np.reshape(x, [-1, 1, self.weight.shape[0]])  # shape = (-1,1,in_size)
        self.data_out = self.Func(self.data_in @ self.weight + self.bias)  # shape =(-1,1,out_size)
        return self.data_out

    def backward(self, grad):
        grad = grad.reshape(self.data_out.shape) * self.Func.grad(self.data_out)  # shape =(-1,1,out_size)
        xgrad = grad @ self.weight.T  # shape =(-1,1,in_size)
        self.bias = self.bias - np.sum(grad, axis=0) * self.lr
        self.weight = self.weight - np.sum(self.data_in.swapaxes(1, 2) @ grad, axis=0) * self.lr
        return xgrad

    def __call__(self, *args, **kwargs):
        return self.forward(*args)


class ClasssificationBPNet:
    def __init__(self, Name='BP_Classification', lr=0.02):
        self.l1 = Linear(8, 8, Name=Name + '_layer1', lr=lr)
        self.l2 = Linear(8, 5, Name=Name + '_layer2', lr=lr)
        self.l3 = Linear(5, 1, Name=Name + '_layer3', lr=lr)

    def forward(self, x):
        x = self.l3(self.l2(self.l1(x)))
        return x.reshape((-1, x.shape[2]))

    def backward(self, grad):
        x = self.l1.backward(self.l2.backward(self.l3.backward(grad)))

    def save(self):
        self.l1.save()
        self.l2.save()
        self.l3.save()

    def load(self):
        self.l1.load()
        self.l2.load()
        self.l3.load()

    def __call__(self, *args, **kwargs):
        return self.forward(*args)


def Classification():
    train_x, train_y = ReadData.getClassificationData('classification/diabetes_train')
    test_x, test_y = ReadData.getClassificationData('classification/diabetes_test')
    Bp = ClasssificationBPNet()
    epochs = 10000
    a = []
    b = []
    maxval_test = 0
    maxval_train = 0
    for epoch in range(epochs):
        dy = Bp(train_x) - train_y
        Bp.backward(2 * dy)
        if (epoch + 1) % 100 == 0:
            loss = np.mean(dy * dy)
            test_dy = Bp(test_x) - test_y
            testloss = np.mean(test_dy * test_dy)
            a.append(loss)
            b.append(testloss)
            print('epoch=%5d loss %.8f testloss %.8f' % (epoch + 1, loss, testloss), end='\r')
        te = np.sum((Bp(test_x) > 0.5) == test_y)
        tr = np.sum((Bp(train_x) > 0.5) == train_y)
        if maxval_test < te:
            maxval_test = te
            maxval_train = tr
            Bp.save()
        print(tr, '\t', tr / len(train_x), te, '\t', te / len(test_x), '\t', end='\r')
    print('best recode')
    print(maxval_train, '\t', maxval_train / len(train_x))
    print(maxval_test, '\t', maxval_test / len(test_x))
    Bp.load()
    print('*' * 20)
    Bp.load()
    haty = (Bp(test_x) > 0.5) * 1
    TP = np.sum((haty == 1) * (test_y == 1))
    TN = np.sum((haty == 0) * (test_y == 0))
    FN = np.sum((haty == 0) * (test_y == 1))
    FP = np.sum((haty == 1) * (test_y == 0))
    print('TP\tFN\t[', TP, ' ', FN, ']')
    print('FP\tTN\t[', FP, ' ', TN, ']')
    print('P =', TP / (TP + TP), ' R=', TP / (TP + FN))
    print('*' * 20)

    plt.figure(1)
    plt.plot(a)
    plt.plot(b)
    plt.show()


def ROC_AUC_Classification():
    test_x, test_y = ReadData.getClassificationData('classification/diabetes_test')
    Bp = ClasssificationBPNet()
    Bp.load()
    predict = Bp(test_x)
    Ttot = np.sum(test_y == 1)
    Ftot = np.sum(test_y == 0)
    point = np.array([[p[0], y[0]] for p, y in zip(predict, test_y)])
    l = len(point)
    for i in range(l):
        j = np.argmax(point[i:, 0]) + i
        t = point[i].copy()
        point[i] = point[j]
        point[j] = t
    cnt_T = 0
    TPR = []
    FPR = []
    for i in range(l):
        cnt_T = cnt_T + point[i][1]
        TPR.append(cnt_T / Ttot)
        FPR.append((i - cnt_T + 1) / Ftot)
    TPR = np.array(TPR)
    FPR = np.array(FPR)
    plt.figure(2)
    plt.plot(FPR, TPR)
    font = FontProperties(fname=r"C:\Windows\Fonts\simhei.ttf", size=14)
    plt.title('Bp神经网络ROC曲线', fontproperties=font)
    plt.xlabel("假正例率", fontproperties=font)
    plt.ylabel("真正例率", fontproperties=font)
    print('AUC is :', np.sum((TPR[1:] + TPR[:-1]) * 0.5 * (FPR[1:] - FPR[:-1])))
    plt.show()


Classification()
ROC_AUC_Classification()

支持向量机cpp版

python跑的太慢了,cpp跑的还快一些,方便调参

#include<bits/stdc++.h>
using namespace std;
class SVM
{
public:
    int dim,datalen;
    double b,**data,*lable,*Lamda,**Mat_dot,**Mat_doty,C_val;
    double (*kennel)(double*,double*,int);
    SVM(int _dim,double (*_kennel)(double*,double*,int),double **x,double *y,int _datalen,double C_val)
    {
        dim=_dim;
        kennel=_kennel;
        datalen=_datalen,data=x,lable=y;
        Mat_dot = new double*[datalen];
        Mat_doty = new double*[datalen];
        for(int i=0; i<datalen; i++)Mat_dot[i]=new double[datalen];
        for(int i=0; i<datalen; i++)Mat_doty[i]=new double[datalen];
        for(int i=0; i<datalen; i++)
            for(int j=i; j<datalen; j++)
            {
                Mat_dot[i][j]=Mat_dot[j][i]=kennel(data[i],data[j],dim);
                Mat_doty[i][j]=Mat_doty[j][i]=Mat_dot[i][j]*lable[i]*lable[j];
            }
        Lamda = new double[datalen];
        double delat = 0;
        for(int i=0; i<datalen; i++)Lamda[i]=rand()%100/100.0,delat+=Lamda[i]*lable[i];
        for(int i=0; i<datalen; i++)
            if(delat*y[i]<0)
            {
                Lamda[i]=Lamda[i]-y[i]*delat;
                delat = 0;
                if(Lamda[i]>C_val)delat=(Lamda[i]-C_val)*y[i],Lamda[i]=C_val;
            }
        double res = 0;
        for(int i=0; i<datalen; i++)res+=Lamda[i]*y[i];
        this->C_val = C_val;
    }
    ~SVM()
    {
        for(int i=0; i<datalen; i++)
            delete Mat_dot[i],delete Mat_doty[i];
        delete Lamda;
        delete Mat_dot;
        double Mat_doty;
    }
    void train(int epochs)
    {
        while(epochs--)
        {
            for(int a=0; a<datalen; a++)
            {
                for(int b=0; b<datalen; b++)
                {
                    double down = Mat_dot[a][a]+Mat_dot[b][b]-2*Mat_dot[a][b];
                    if(down<1e-9)continue;
                    double sum_Lam_a = 0,sum_Lam_b=0;
                    for(int i=0; i<datalen; i++)
                        sum_Lam_a+=Lamda[i]*Mat_doty[i][a],sum_Lam_b+=Lamda[i]*Mat_doty[i][b];
                    sum_Lam_a-=Lamda[a]*Mat_doty[a][a]+Lamda[b]*Mat_doty[b][a];
                    sum_Lam_b-=Lamda[a]*Mat_doty[a][b]+Lamda[b]*Mat_doty[b][b];
                    double C = -Lamda[a]*lable[a]-Lamda[b]*lable[b];
                    double up =lable[a]*C*(Mat_dot[a][b]-Mat_dot[b][b])+1 - lable[a]*lable[b]-sum_Lam_a+lable[a]*lable[b]*sum_Lam_b;

                    double na =up/down,nb=-(C+na*lable[a])*lable[b],rate=1;
                    if(na<0)rate =min(rate,(0-Lamda[a])/(na-Lamda[a]));
                    if(nb<0)rate =min(rate,(0-Lamda[b])/(nb-Lamda[b]));
                    if(na>C_val)rate =min(rate,(C_val-Lamda[a])/(na-Lamda[a]));
                    if(nb>C_val)rate =min(rate,(C_val-Lamda[b])/(nb-Lamda[b]));
                    Lamda[a]+=(na-Lamda[a])*rate,Lamda[b]+=(nb-Lamda[b])*rate;
                }
                printf("<c_val>=%4.0f<a,b>=%d,**\r",C_val,a);
            }
        }


        double maxb=0,minb=0;
        for(int i=0; i<datalen; i++)
        {
            if(Lamda[i]<1e-9)continue;
            double t=0;
            for(int j=0; j<datalen; j++)t-=Lamda[j]*lable[j]*Mat_dot[j][i];
            if(i==0)maxb=minb=t;
            maxb=max(maxb,t);
            minb=min(minb,t);
        }
        b=(maxb+minb)/2;
    }
    double predict(double* x)
    {
        double res = b;
        for(int i =0; i<datalen; i++)
            res+=Lamda[i]*lable[i]*kennel(data[i],x,dim);
        return res>0?1:-1;
    }
    int predict(double **x,double *y,int _datalen)
    {
        int ans = 0;
        for(int i=0; i<_datalen; i++)
            ans+= abs(predict(x[i])-y[i])<1e-5?1:0;
        return ans;
    }
};
const double pi = acos(-1);
double guassKennel(double*x,double*y,int len)
{
    static double gamma = 1.0,down = 1/(sqrt(2)*gamma);
    double res = 0;
    for(int i=0; i<len; i++)res +=(x[i]-y[i])*(x[i]-y[i]);
    return down*exp(-res*down*down);
}
double LinearKennel(double*x,double*y,int len)
{
    double res = 0;
    for(int i=0; i<len; i++)res += x[i]*y[i];
    return res;
}
char ch[60000];
int p;
int readdouble(double&x)
{
    while(p<60000&!(ch[p]>='0'&&ch[p]<='9'))p++;
    if(p==60000)return 0;
    x=0;
    while(p<60000&&ch[p]>='0'&&ch[p]<='9')x=x*10+ch[p]-48,p++;
    if(ch[p]!='.')return 1;
    p++;
    double base=0.1;
    while(p<60000&&ch[p]>='0'&&ch[p]<='9')x+=(ch[p]-48)*base,base*=0.1,p++;
    return 1;
}

class ReadData
{
public:
    int lineNum,Maxlen;
    double **data,*label;
    ReadData(int dim,int maxlen,FILE* file)
    {
        Maxlen=maxlen;
        lineNum=0;
        label=new double[maxlen];
        data = new double*[maxlen];
        for(int i=0; i<maxlen; i++)data[i]=new double[dim];
        memset(ch,0,sizeof(ch));
        fread(ch,1,60000,file);
        p=0;
        while(readdouble(label[lineNum]))
        {
            label[lineNum]=label[lineNum]*2-1;
            for(int i=0; i<8; i++)readdouble(data[lineNum][i]);
            swap(data[lineNum][2],data[lineNum][7]);
            lineNum++;
        }
    }
    ~ReadData()
    {
        for(int i=0; i<Maxlen; i++)delete data[i];
        delete label;
        delete data;
    }
};
const double inf = 1e18;
int main()
{
    srand(time(NULL));


    FILE* train_file = fopen("classification/diabetes_train","r");
    FILE* test_file = fopen("classification/diabetes_test","r");
    ReadData train = ReadData(8,600,train_file);
    ReadData test = ReadData(8,200,test_file);
    fclose(test_file);
    fclose(train_file);

    for(int i=1; i<100; i++)
    {
        SVM* svm =new SVM(8,guassKennel,train.data,train.label,train.lineNum,i*500);
        for(int epoch=1;epoch<=5;epoch++){
            svm->train(1);
            printf("C=%d   epoch=%3d\t",500*i,epoch);
            printf("train %d/%d ",svm->predict(train.data,train.label,train.lineNum),train.lineNum);
            printf("test %d/%d\n",svm->predict(test.data,test.label,test.lineNum),test.lineNum);
        }
        delete svm;
    }
    return 0;
}

BP神经网络回归

class RegressionBPNet:
    def __init__(self, lr=0.5):
        self.l1 = Linear(1, 15, lr=lr)
        self.l2 = Linear(15, 1, lr=lr)

    def forward(self, x):
        x = self.l2(self.l1(x))
        return x.reshape((-1, x.shape[2]))

    def backward(self, grad):
        x = self.l1.backward(self.l2.backward(grad))

    def __call__(self, *args, **kwargs):
        return self.forward(*args)

def Regression():
    train_x, train_y = ReadData.getRegressionData('regression/sinc_train')
    test_x, test_y = ReadData.getRegressionData('regression/sinc_test')
    Bp = RegressionBPNet(lr=0.0015)

    maxy = np.max(train_y) + 0.2
    miny = np.min(train_y) - 0.2
    train_y = train_y / (maxy - miny) - miny / (maxy - miny)
    test_y = test_y / (maxy - miny) - miny / (maxy - miny)

    epochs = 14000
    a = []
    b = []
    for epoch in range(epochs):
        dy = Bp(train_x) - train_y
        Bp.backward(2 * dy)
        if (epoch + 1) % 100 == 0:
            loss = np.mean(dy * dy)
            test_dy = Bp(test_x) - test_y
            testloss = np.mean(test_dy * test_dy)
            a.append(loss)
            b.append(testloss)
            print('epoch=%5d loss %.12f testloss %.12f' % (epoch + 1, loss, testloss), end='\r')
    # plt.plot(a)
    # plt.plot(b)
    x = np.arange(-10, 10, 0.1)
    y = Bp(x)
    plt.plot(test_x, test_y, 'o')
    plt.plot(x, y)
    plt.show()


Regression()

多元线性回归

import numpy as np
import matplotlib.pyplot as plt
import ReadData


def linear_regression(x, y):
    w = np.linalg.inv(x.T @ x) @ x.T @ y
    return w


train_x, train_y = ReadData.getRegressionData('regression/sinc_train')
test_x, test_y = ReadData.getRegressionData('regression/sinc_test')

x = np.concatenate((train_x ** 8, train_x ** 6, train_x ** 4, train_x ** 2, np.ones([len(train_x), 1])), axis=1)
w = linear_regression(x, train_y)  # 求解模型
print(w)
# 绘制train数据
v = x @ w
plt.figure(1)
plt.plot(train_x[:, 0], train_y[:, 0], 'o', label='train_data')
plt.plot(train_x[:, 0], [_[0] for _ in v], 'o', label='predict')
plt.legend()
plt.show()
# 绘制test数据
x = np.concatenate((test_x ** 8, test_x ** 6, test_x ** 4, test_x ** 2, np.ones([len(test_x), 1])), axis=1)
v = x @ w
plt.figure(2)
plt.plot(test_x[:, 0], [_[0] for _ in test_y], 'o', label='test_data')
plt.plot(test_x[:, 0], [_[0] for _ in v], 'o', label='predict')
plt.legend()
plt.show()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值