做一个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

data = pd.read_csv('./data/iris.csv')
print(data.head())
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

我们分别用0,1,2来表示[‘setosa‘ ‘versicolor‘ ‘virginica‘]

整理

首先,我们对数据集进行一个简单的整理。我们需要把分类替换成0,1,2

其次,我们把数据集分成两个分类,一个用来训练我们的logitic算法的参数,另外一个用来测试我们的训练的结果

以下是代码:

# 数值替换

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)

我们需要把label编程1ofN的样式

经过上述两步的操作,我们可以看到数据集被分成两个部分。我们接下来对数据进行logitic分类。

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.]]

分类

思路

我选选择先易后难的方法来处理这个问题:

如果我们有两个分类0或者1的话,我们需要判断特征值X(N维)是否可以归为某个分类。我们的步骤如下:

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

现在有多个分类, 我们就需要使用one-to-many的方法去计算。简单的理解,在本题中,一共有3个分类。我们需要计算\(\hat{y}_1\)来表明这个东西是分类1或者不是分类1的概率 \(\hat{y}_2\)是不是分类2的概率,\(\hat{y}_3\)是不是分类3的概率。然后去比较这三个分类那个概率最大,就是哪个的概率。

比较属于哪个概率大的算法,我们用softmat。就是计算\(exp(\hat{y}_1)\),\(exp(\hat{y}_2)\),\(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]

上述代码是我们只求一条记录的代码,下面我们给他用矩阵化修改为一次计算全部的训练集的\(\hat{y}\)

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和b,就是机器学习的过程
\[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

从上述运行结果中来看,达到了96.67%的预测准确度。还不错!

原文地址:https://www.cnblogs.com/bbird/p/11544410.html

时间: 2024-08-29 11:45:43

做一个logitic分类之鸢尾花数据集的分类的相关文章

探索sklearn|鸢尾花数据集

1 鸢尾花数据集背景 鸢尾花数据集是原则20世纪30年代的经典数据集.它是用统计进行分类的鼻祖. sklearn包不仅囊括很多机器学习的算法,也自带了许多经典的数据集,鸢尾花数据集就是其中之一. 导入的方法很简单,不过我比较好奇它是如何来存储这些数据的,于是我决定去背后看一看 from sklearn.datasets import load_iris data = load_iris() 找到sklearn包的路径,发现包可不少,不过现在扔在一边,以后再来探索,我现在要找到是datasets文

做一个会PS切图的前端开发

系列链接 做一个会使用PS的前端开发 做一个会PS切图的前端开发 切图方法分类 PhotoShop从CS版本演变到现在的CC版本,切图功能发生了比较大的变化,我们可以把PhotoShop CS版本时的切图功能称为传统切图,而从PhotoShop CC版本开始PS提出了精准切图.所谓传统切图就是切图人员基本上都是自己分割图层切图,传统切图又分为全手工切图和参考线切图:现在CC版本提出的精准切图,切图人员可以依赖计算机把图层对象精确的切割出来,这样切割出来的图层肯定比传统切图切出来的精准度高.另一方

我想做一个合格的工程师

我想吐槽下,在新公司经过三个月的试用期,前两天终于完成了转正答辩,其实答辩就是两个我们项目组的两个项目经理(一个项目经理马上要离任了,另外一个新来的两个月,继任前者作为项目经理.),还有一个人事的同事.连一个部门经理或者稍大点的领导都没有参与我的答辩.感觉答辩的意义都没有了,但是巨坑的是,新项目经理说“有木有打算培训班学习想法”,“对数据库的应用要学习学习”,我想这不是赤裸裸讽刺我基础太差么?其实我确实来这家公司之前,没有用过MVC,这个能力也学稍弱与这个项目经理.但是我可以讲,我的其他能力绝对

做一个日收入1000元的APP!

[导语]虽然讲了很多个人开发者的文章,但新手开发者如何赚自己的第一个100块钱,确是最难的事情.群里有人说都不知道干什么 app赚钱,完全没有想法, 并且经常问我有什么快速赚钱的方法.我只能遗憾地说,我真不知道.又有很多人说,现在市场上什么app都有了,完全没希望了,这种话我真的不想听. 我虽然不能告诉大家怎么赚大钱,因为我自己也赚得不多,但是我把自己的经验分享给大家,希望你们能赚大钱. 一.挖掘细分市场 大家普遍知道搞视频播放(类似优酷).搞阅读(类似掌阅).搞电商(类似京东)都能赚钱,但是这

前端的小玩意(9.4)——做一个仿360工具箱的web页面(自动生成所有图标,对图标添加响应逻辑)

前端的小玩意(9.1)--做一个仿360工具箱的web页面(Tab按钮切换) http://blog.csdn.net/qq20004604/article/details/52216203 前端的小玩意(9.2)--做一个仿360工具箱的web页面(全部工具里面的模板) http://blog.csdn.net/qq20004604/article/details/52226223 前端的小玩意(9.3)--做一个仿360工具箱的web页面(我的工具里的模板和样式) http://blog.c

【Bugly干货分享】一起用 HTML5 Canvas 做一个简单又骚气的粒子引擎

Bugly 技术干货系列内容主要涉及移动开发方向,是由Bugly邀请腾讯内部各位技术大咖,通过日常工作经验的总结以及感悟撰写而成,内容均属原创,转载请标明出处. 前言 好吧,说是“粒子引擎”还是大言不惭而标题党了,离真正的粒子引擎还有点远.废话少说,先看[demo],扫描后点击屏幕有惊喜哦… 本文将教会你做一个简单的canvas粒子制造器(下称引擎). 世界观 这个简单的引擎里需要有三种元素:世界(World).发射器(Launcher).粒子(Grain).总得来说就是:发射器存在于世界之中,

初识Scrapy,在充满爬虫的世界里做一个好公民

欢迎来到你的Scrapy之旅.通过本文,我们旨在将你从一个只有很少经验甚至没有经验的Scrapy初学者,打造成拥有信心使用这个强大的框架从网络或者其他源爬取大数据集的Scrapy专家.本文将介绍Scrapy,并且告诉你一些可以用它实现的很棒的事情. 1.1 初识Scrapy Scrapy是一个健壮的网络框架,它可以从各种数据源中抓取数据.作为一个普通的网络用户,你会发现自己经常需要从网站上获取数据,使用类似Excel的电子表格程序进行浏览,以便离线访问数据或者执行计算.而作为一个开发者,你需要经

做一个拥有自己站点的java程序员

有个事情和大家分享下,有个自己做了三年java开发的人问我,说想建一个博客类型的网站,主要发表个人的文章,然后用户可以留言,大概就是这么个简单的东西,应该怎么去做.我耐心的和他解释道,应该按照什么样的步骤去做,我解释完后满以为他已经完全懂了,毕竟就这么点东西,很多不是搞技术开发的人,像前十年前的很多站长都是拿本书自学和不断的在百度,很多建的站都是风生水起,我觉得程序员是自带建站光环的,所以解释完毕后以为就功德圆满了.过了一段时间,这个人又找到我,并发给我了一个ip地址,说个人站建好了,叫我看看并

手把手教你用苹果cms做一个电影视频网站 可直接在线播放

现在大家在网上看电影很方便了,因为电影网站多如牛毛!那很多人在想,做电影网站难么?能否拥有一个属于自己的电影网站呢?其实真的可以,而且很简单下面我们就来手把手的教你如何做一个电影网站!因为我的空间是PHP的,只能选择PHP CMS,影视网站的CMS有很多,飞飞.苹果.海洋.PHPVOD等等,之所以选择苹果CMS,有几点: 1.选择一套电影网站建站系统(CMS),这个非常重要,建站系统说白了就是集成化后台管理,把网站当成博客来运营,但关键是你得知道有哪些电影建站系统?而自己应该选哪一个比较适合?