线性逻辑回归的代码实现

载入数据

data = np.genfromtxt(r'data.csv', delimiter=',')
x_data = data[:, :-1]  # 特征
y_data = data[:, -1]  # 标签

可以看到,这个数据集有3列,前两列为特征,最后一列‘1’和‘0’为标签

逻辑回归shap代码 逻辑回归代码实现_逻辑回归shap代码


作图观察数据集

def plot():
    x0 = []
    x1 = []
    y0 = []
    y1 = []
    # 切分不同类别的数据
    for i in range(len(x_data)):
        if y_data[i] == 0:  # 0类别
            x0.append(x_data[i, 0])
            y0.append(x_data[i, 1])
        else:  # 1类别
            x1.append(x_data[i, 0])
            y1.append(x_data[i, 1])
    #画图
    scatter0 = plt.scatter(x0, y0, c='b', marker='o')  # 蓝色圆点表示0类别
    scatter1 = plt.scatter(x1, y1, c='r', marker='x')  # 红色×表示1类别
    #画图例
    plt.legend(handles=[scatter0, scatter1], labels=['label0', 'label1'], loc='best')

plot()
plt.show()

逻辑回归shap代码 逻辑回归代码实现_数据_02

# 数据处理,添加偏置项
x_data = data[:, :-1]
y_data = data[:, -1, np.newaxis]
# 给样本添加偏置项(x_data是100行2列的数据,y_data是100行1列的数据)
# 可用np.mat(x_data).shape测试
X_data = np.concatenate((np.ones((100, 1)), x_data), axis=1)

到这里,数据准备的工作完成

X_data为100行3列的数据,第0列是我们添加的偏置,都为1,后两列为特征值

逻辑回归shap代码 逻辑回归代码实现_逻辑回归_03

梯度下降法实现逻辑回归

定义sigmoid函数:

逻辑回归shap代码 逻辑回归代码实现_数据_04


逻辑回归shap代码 逻辑回归代码实现_数据集_05


逻辑回归shap代码 逻辑回归代码实现_逻辑回归shap代码_06


逻辑回归shap代码 逻辑回归代码实现_逻辑回归shap代码_07


整个计算过程则是根据上面的几张图来进行

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

定义代价函数

def cost(xMat, yMat, ws):
    left = np.multiply(yMat, np.log(sigmoid(xMat*ws)))
    right = np.multiply(1-yMat, np.log(1-sigmoid(xMat*ws)))
    return np.sum(left + right) / -(len(xMat))

定义梯度下降方法

def gradDscent(xArr, yArr):
    if scale == True:
        xArr = preprocessing.scale(xArr)
    xMat = np.mat(xArr)
    yMat = np.mat(yArr)
    lr = 0.001
    epochs = 10000
    costList = []
    # 计算数据行列数
    # 行代表数据个数,列代表权值个数
    m, n = np.shape(xMat)
    # 初始化权值
    ws = np.mat(np.ones((n, 1)))

    for i in range(epochs + 1):
        # xMat和weights矩阵相乘
        h = sigmoid(xMat * ws)
        # 计算误差
        ws_grad = xMat.T*(h - yMat)/m
        ws = ws - lr * ws_grad
        if i % 50 == 0:
            costList.append(cost(xMat, yMat, ws))
    return ws, costList
# 模型训练,得到权值和cost值的变化
ws, costList = gradDscent(X_data, y_data)
print(ws)

计算结果

# 模型训练,得到权值和cost值的变化
ws, costList = gradDscent(X_data, y_data)
print(ws)

画出决策边界

if scale == True:
    #画图决策边界
    plot()
    x_test = [[-4], [3]]
    y_test = (-ws[0] - x_test * ws[1]) / ws[2]
    plt.plot(x_test, y_test, 'K')
    plt.show()

逻辑回归shap代码 逻辑回归代码实现_数据集_08


补充:y的求解

前边已经求出了3个权重,则转化为等式

w1x+w2y+w0b=0
y=(-b-w1
x)/w2
,其中,b=1

画出损失函数(costLost)变化曲线:

x = np.linspace(0, 10000, 201)
plt.plot(x, costList, c='r')
plt.title('Train')
plt.xlabel('Epochs')
plt.ylabel('Cost')
plt.show()

逻辑回归shap代码 逻辑回归代码实现_数据集_09


最后进行预测

导入classification_report

from sklearn.metrics import classification_report
def predict(x_data, ws):
    if scale == True:
        x_data = preprocessing.scale(x_data)
    xMat = np.mat(x_data)
    ws = np.mat(ws)
    # 大于0.5取1,否则返回0
    return[1 if x >= 0.5 else 0 for x in sigmoid(xMat*ws)]


predictions = predict(X_data, ws)
print(classification_report(y_data, predictions))

逻辑回归shap代码 逻辑回归代码实现_逻辑回归_10


最后可以看到,属于‘1’类的有53个,属于‘0’类的有47个。

sklearn实现逻辑回归

前期的数据处理完全一样,直接从构建模型开始

logistic = linear_model.LogisticRegression()
logistic.fit(x_data, y_data)

画决策边界,计算方法与梯度下降法中的说明一致。

if scale==False:
    # 画图决策边界
    plot()
    x_test = np.array([[-4], [3]])
    y_test = (-logistic.intercept_ -x_test*logistic.coef_[0][0])/logistic.coef_[0][1]
    plt.plot(x_test, y_test, 'k')
    plt.show()

print(logistic.coef_)  # 代表权值,但是二维的数据,所以取值时[0][0]或者[0][1]

逻辑回归shap代码 逻辑回归代码实现_逻辑回归shap代码_11


最后利用classification_report做预测

predictions = logistic.predict(x_data)
print(classification_report(y_data, predictions))

逻辑回归shap代码 逻辑回归代码实现_数据_12