# 06.2 线性二分类实现

## 6.2 用神经网络实现线性二分类⚓︎

1. 从视觉上判断是线性可分的，所以我们使用单层神经网络即可；
2. 输入特征是经度和纬度，所以我们在输入层设置两个输入单元。其中$x_1=$经度，$x_2=$纬度；
3. 最后输出的是一个二分类结果，分别是楚汉地盘，可以看成非0即1的二分类问题，所以我们只用一个输出单元就可以了。

### 6.2.1 定义神经网络结构⚓︎

#### 输入层⚓︎

X=\begin{pmatrix} x_{1} & x_{2} \end{pmatrix}

#### 权重矩阵⚓︎

W=\begin{pmatrix} w_{1} \\\\ w_{2} \end{pmatrix}

$B$ 的尺寸是 $1\times 1$，行数永远是1，列数永远和 $W$ 一样。

B=\begin{pmatrix} b \end{pmatrix}

#### 输出层⚓︎

\begin{aligned} z &= X \cdot W + B =\begin{pmatrix} x_1 & x_2 \end{pmatrix} \begin{pmatrix} w_1 \\\\ w_2 \end{pmatrix} + b \\\\ &=x_1 \cdot w_1 + x_2 \cdot w_2 + b \end{aligned} \tag{1} a = Logistic(z) \tag{2}

#### 损失函数⚓︎

loss(W,B) = -[y\ln a+(1-y)\ln(1-a)] \tag{3}

### 6.2.2 反向传播⚓︎

\frac{\partial loss}{\partial w}= \begin{pmatrix} \frac{\partial loss}{\partial w_1} \\\\ \frac{\partial loss}{\partial w_2} \end{pmatrix}  =\begin{pmatrix} \frac{\partial loss}{\partial z}\frac{\partial z}{\partial w_1} \\\\ \frac{\partial loss}{\partial z}\frac{\partial z}{\partial w_2} \end{pmatrix} =\begin{pmatrix} (a-y)x_1 \\\\ (a-y)x_2 \end{pmatrix}  =(x_1 \ x_2)^{\top} (a-y) \tag{4}

\frac{\partial J(W,B)}{\partial W}= \begin{pmatrix} x_{11} & x_{12} \\\\ x_{21} & x_{22} \\\\ x_{31} & x_{32} \end{pmatrix}^{\top} \begin{pmatrix} a_1-y_1 \\\\ a_2-y_2 \\\\ a_3-y_3 \end{pmatrix} =X^{\top}(A-Y) \tag{5}

### 6.2.3 代码实现⚓︎

class NetType(Enum):
Fitting = 1,
BinaryClassifier = 2,
MultipleClassifier = 3,


class HyperParameters(object):
def __init__(self, eta=0.1, max_epoch=1000, batch_size=5, eps=0.1, net_type=NetType.Fitting):
self.eta = eta
self.max_epoch = max_epoch
self.batch_size = batch_size
self.eps = eps
self.net_type = net_type


class Logistic(object):
def forward(self, z):
a = 1.0 / (1.0 + np.exp(-z))
return a


class LossFunction(object):
def __init__(self, net_type):
self.net_type = net_type
# end def

def MSE(self, A, Y, count):
...

# for binary classifier
def CE2(self, A, Y, count):
...


class NeuralNet(object):
def __init__(self, params, input_size, output_size):
self.params = params
self.W = np.zeros((input_size, output_size))
self.B = np.zeros((1, output_size))

def __forwardBatch(self, batch_x):
Z = np.dot(batch_x, self.W) + self.B
if self.params.net_type == NetType.BinaryClassifier:
A = Sigmoid().forward(Z)
return A
else:
return Z


if __name__ == '__main__':
......
params = HyperParameters(eta=0.1, max_epoch=100, batch_size=10, eps=1e-3, net_type=NetType.BinaryClassifier)
......


### 6.2.4 运行结果⚓︎

......
99 19 0.20742586902509108
W= [[-7.66469954]
[ 3.15772116]]
B= [[2.19442993]]
A= [[0.65791301]
[0.30556477]
[0.53019727]]


1. 经纬度相对值为(0.58,0.92)时，概率为0.65，属于汉；
2. 经纬度相对值为(0.62,0.55)时，概率为0.30，属于楚；
3. 经纬度相对值为(0.39,0.29)时，概率为0.53，属于汉。

ch06, Level2