# 做一个logitic分类之鸢尾花数据集的分类

## 做一个logitic分类之鸢尾花数据集的分类

Iris 鸢尾花数据集是一个经典数据集，在统计学习和机器学习领域都经常被用作示例。数据集内包含 3 类共 150 条记录，每类各 50 个数据，每条记录都有 4 项特征：花萼长度、花萼宽度、花瓣长度、花瓣宽度，可以通过这4个特征预测鸢尾花卉属于（iris-setosa, iris-versicolour, iris-virginica）中的哪一品种。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

print(data.info())
print(data['Species'].unique())
Unnamed: 0  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width Species
0           1           5.1          3.5           1.4          0.2  setosa
1           2           4.9          3.0           1.4          0.2  setosa
2           3           4.7          3.2           1.3          0.2  setosa
3           4           4.6          3.1           1.5          0.2  setosa
4           5           5.0          3.6           1.4          0.2  setosa
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 150 entries, 0 to 149
Data columns (total 6 columns):
Unnamed: 0      150 non-null int64
Sepal.Length    150 non-null float64
Sepal.Width     150 non-null float64
Petal.Length    150 non-null float64
Petal.Width     150 non-null float64
Species         150 non-null object
dtypes: float64(4), int64(1), object(1)
memory usage: 7.2+ KB
None
['setosa' 'versicolor' 'virginica']

1. setosa
2. versicolor
3. virginica

## 整理

# 数值替换

data.loc[data['Species']=='setosa','Species']=0
data.loc[data['Species']=='versicolor','Species']=1
data.loc[data['Species']=='virginica','Species']=2
print(data)
Unnamed: 0  Sepal.Length  Sepal.Width  Petal.Length  Petal.Width  Species
0             1           5.1          3.5           1.4          0.2        0
1             2           4.9          3.0           1.4          0.2        0
2             3           4.7          3.2           1.3          0.2        0
3             4           4.6          3.1           1.5          0.2        0
4             5           5.0          3.6           1.4          0.2        0
..          ...           ...          ...           ...          ...      ...
145         146           6.7          3.0           5.2          2.3        2
146         147           6.3          2.5           5.0          1.9        2
147         148           6.5          3.0           5.2          2.0        2
148         149           6.2          3.4           5.4          2.3        2
149         150           5.9          3.0           5.1          1.8        2

[150 rows x 6 columns]
#分割训练集和测试集
train_data = data.sample(frac=0.6,random_state=0,axis=0)
test_data = data[~data.index.isin(train_data.index)]

train_data = np.array(train_data)
test_data = np.array(test_data)

train_label = train_data[:,5:6].astype(int)
test_label = test_data[:,5:6].astype(int)

print(train_label[:1])
print(test_label[:1])

train_data = train_data[:,1:5]
test_data = test_data[:,1:5]

print(np.shape(train_data))
print(np.shape(train_label))
print(np.shape(test_data))
print(np.shape(test_label))
[[2]]
[[0]]
(90, 4)
(90, 1)
(60, 4)
(60, 1)

train_label_onhot = np.eye(3)[train_label]
test_label_onhot = np.eye(3)[test_label]
train_label_onhot = train_label_onhot.reshape((90,3))
test_label_onhot =  test_label_onhot.reshape((60,3))
print(train_label_onhot[:3])
[[0. 0. 1.]
[0. 1. 0.]
[1. 0. 0.]]

## 分类

### 思路

1. 初始化参数w（1，N）和b(1)
2. 计算 $z = \sum_{i=0}^{n}w*x + b$
3. 带入 $\sigma$ 函数得到 $\hat{y}=\sigma(z)$

,

$exp(\hat{y}_3)$

,然后得到属于三个分类的概率分别是

1. p1= $\frac{exp(\hat{y}_1)}{\sum_{i=0}{3}(\hat{y}_i)}$
2. p1= $\frac{exp(\hat{y}_2)}{\sum_{i=0}{3}(\hat{y}_i)}$
3. p1= $\frac{exp(\hat{y}_3)}{\sum_{i=0}{3}(\hat{y}_i)}$

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

w = np.random.rand(4,3)
b = np.random.rand(3)

def get_result(w,b):
z = np.matmul(train_data[0],w) +b
y = sigmoid(z)
return y

y = get_result(w,b)

print(y)
[0.99997447 0.99966436 0.99999301]

def get_result_all(data,w,b):
z = np.matmul(data,w)+ b
y = sigmoid(z)
return y
y=get_result_all(train_data,w,b)
print(y[:10])
[[0.99997447 0.99966436 0.99999301]
[0.99988776 0.99720719 0.9999609 ]
[0.99947512 0.98810796 0.99962362]
[0.99999389 0.99980632 0.999999  ]
[0.9990065  0.98181945 0.99931113]
[0.99999094 0.9998681  0.9999983 ]
[0.99902719 0.98236513 0.99924728]
[0.9999761  0.99933525 0.99999313]
[0.99997542 0.99923594 0.99999312]
[0.99993082 0.99841774 0.99997519]]

$loss=−\sum_{i=0}^{n}[y_iln\hat{y}_i+(1−y_i)ln(1−\hat{y}_i)]$

### 当 $y_i=0$ 时

#### w的导数为：

$\frac{dloss}{dw}=(1-y_i)*\frac{1}{1-\hat{y}_i}*\hat{y}_i*(1-\hat{y}_i)*x_i$

$\frac{dloss}{dw}=\hat{y}*x_i=(\hat{y}-y)*x_i$

#### b的导数为

$\frac{dloss}{db}=(1-y_i)*\frac{1}{1-\hat{y}_i}*\hat{y}_i*(1-\hat{y}_i)$

$\frac{dloss}{db}=\hat{y}-y$

### 当 $y_i$ =1时

#### w的导数

$\frac{dloss}{dw}=-yi*\frac{1}{\hat{y}}*\hat{y}(1-\hat{y})*x_i$

$\frac{dloss}{dw}=(\hat{y}-1)*x_i=(\hat{y}-y)*x_i$

#### b的导数

$\frac{dloss}{dw}=\hat{y}-y$

$\frac{dloss}{dw}=\sum_{i=0}^{n}(\hat{y}-y)*x_i$

$\frac{dloss}{db}=\sum_{i=0}^{n}(\hat{y}-y)$

$w=w-learning_rate*dw$

$b=b-learning_rate*db$

learning_rate = 0.0001

def eval(data,label, w,b):
y = get_result_all(data,w,b)
y = y.argmax(axis=1)
y = np.eye(3)[y]
count = np.shape(data)[0]
acc = (count - np.power(y-label,2).sum()/2)/count
return acc

def train(step,w,b):
y = get_result_all(train_data,w,b)
loss = -1*(train_label_onhot * np.log(y) +(1-train_label_onhot)*np.log(1-y)).sum()

dw = np.matmul(np.transpose(train_data),y - train_label_onhot)
db = (y - train_label_onhot).sum(axis=0)

w = w - learning_rate * dw
b = b - learning_rate * db
return w, b,loss

loss_data = {'step':[],'loss':[]}
train_acc_data = {'step':[],'acc':[]}
test_acc_data={'step':[],'acc':[]}

for step in range(3000):
w,b,loss = train(step,w,b)
train_acc = eval(train_data,train_label_onhot,w,b)
test_acc = eval(test_data,test_label_onhot,w,b)

loss_data['step'].append(step)
loss_data['loss'].append(loss)

train_acc_data['step'].append(step)
train_acc_data['acc'].append(train_acc)

test_acc_data['step'].append(step)
test_acc_data['acc'].append(test_acc)

plt.plot(loss_data['step'],loss_data['loss'])
plt.show()

plt.plot(train_acc_data['step'],train_acc_data['acc'],color='red')
plt.plot(test_acc_data['step'],test_acc_data['acc'],color='blue')
plt.show()
print(test_acc_data['acc'][-1])

[png]

0.9666666666666667