用TensorFlow进行逻辑回归(二)

逻辑回归的例子

逻辑回归是经典的分类算法。为了简单,我们考虑二分类。这意味着,我们要处理识别二个分类的问题,我们的标签为 0 1 我们要一个与线性回归不同的激活函数,不同的损失函数,神经元的输出略有不同。我们的目的是能构建模型能预测一个新的观察属于两个分类中的哪一个。 对于输入 x神经元应输出概率P(y = 1| x) 作为分类1.我们分类观察作为分类1,如果 P(y = 1| x) > 0.5, 或者分类 0,如果P(y = 1| x) < 0.5.

损失函数

作为损失函数,我们使用交叉熵. 对于一个观察函数为

对于多于一个观察 失函数是求和所有的观察

后面我们可以从头书写完整的逻辑回归,但是现在,tensorflow会为我们处理细节--微分,梯度下降,等的实现。我们只需要构建对的神经元。

激活函数

记住:我们想要神经元输出观察是分类 0或分类 1的概率。因些,我们想要激活函数输出0 1的值。否则我们不能把它作为概率。对于逻辑回归,我们使用 sigmoid函数作为激活函数.

数据集

要构建一个有趣的模型,我们要使用修改版的 MNIST数据集。你可以在 http://yann.lecun.com/exdb/ mnist/找到相关信息。

 MNIST数据集是大的手写字数据集可以用来训练我们的模型。 MNIST数据集包含70,000张图像。 原始的黑白图像 (bilevel)来自NIST的大小被归一化以适合 20×20像素盒子而保留它们的比例.结果图像包含灰度水平作为归一化算法使用的  anti-aliasing技术的结果。图像集中于 28×28图像,通过计算像素质心,我后转换图像使中心在28×28 区域内” (来源: http://yann. lecun.com/exdb/mnist/).

我们的特征是每个像素的灰度值,所以我们有28 × 28 = 784个特征取值为0255 (灰度值).数据集包含10个数字,从09. 用下面的代码,你可以准备数据以供下一节使用。通常,我们先导入必要的库.

 #List3-46

from  sklearn.datasets  import  fetch_mldata

然后加载数据.

mnist = fetch_mldata('MNIST original') X,y  =  mnist["data"],  mnist["target"]

现在X包含输入图像且y是目标标签 (记住在机器学习里我们想要预测的值称为目标). 只要输入 X.shape就会得到 X的形状: (70000, 784). 注意 X 70,000 (每行是一张图像) 784 (每列是一个特征,或像素灰度值,本例中).我们检查一下数据集里有多少个数字.

 #List3-47

for i in range(10):

print ("digit", i, "appears", np.count_nonzero(y == i), "times")

结果如下:

digit

0

appears

6903

times

digit

1

appears

7877

times

digit

2

appears

6990

times

digit

3

appears

7141

times

digit

4

appears

6824

times

digit

5

appears

6313

times

digit

6

appears

6876

times

digit

7

appears

7293

times

digit

8

appears

6825

times

digit

9

appears

6958

times

定义一个函数来可视化数字是有用的.

 #List3-48

def  plot_digit(some_digit):

some_digit_image    =    some_digit.reshape(28,28)  plt.imshow(some_digit_image,    cmap    =    matplotlib.cm.binary,    interpolation

= "nearest") plt.axis("off") plt.show()

例如, 我们随机的作图 (见图 3-46).

plot_digit(X[36003])

3-46. 数据集里第 36,003个数字,它很容易的识别为 5

我们这里要实现的模型是二分类的简单的逻辑回归。所以数据集必须减少为两个分类,这种情况,两个数字。我们选择12.我们提取数据集,只呈现 1 2. 我们的神经元会试图识别给定的图像是分类 0 (数字 1)还是分类 1 (数字 2).

X_train = X[np.any([y == 1,y == 2], axis = 0)] y_train  =  y[np.any([y  ==  1,y  ==  2],  axis  =  0)]

接下来,输入观察必须归一化. (注意,当你使用 sigmoid 激活函数时你不想让你的输入数据过大,因为有784个值.)

X_train_normalised   =   X_train/255.0

我们选择 255,因为特征是像素灰度值,取值为 0255.后面我们讨论为什么要归一化输入特征。现在相信我这是必要的步骤。 每一列,我们想要一个输入观察,每一行表示特征,所以我们要改变张量的形状

X_train_tr  =  X_train_normalised.transpose() y_train_tr    =    y_train.reshape(1,y_train.shape[0])

我们可以定义变量n_dim 包含特征数

n_dim    =    X_train_tr.shape[0]

现在时重点。数据集的标签为 1 2 (它们只告诉你图像表示哪个数字). 然而,我们要构建我们的损失函数使用分类标签为01, 所以我们要改变 y_train_tr数组的尺度。

注意    当处理二分类时,记得检查标签的值。有时候,使用错误的标签 (不是 0 1)会浪费很多时间来理解模型为什么不工作。

y_train_shifted = y_train_tr - 1

现在所有表示 1的图像来标签 0, 所有表示2的图像有标签 1.最后,我们给变理合适的名称.

Xtrain = X_train_tr ytrain  =  y_train_shifted

3-47展示了我们处理的数字.

3-47. 从数据集随机选取的6个数字。相对的标签在括号里 (记住现在标签为0 1).

tensorflow实现

 tensorflow实现并不难,与线性回归几乎相同。首先定义placeholdersvariables.

tf.reset_default_graph()

X  =  tf.placeholder(tf.float32,  [n_dim,  None]) Y   =   tf.placeholder(tf.float32,  [1,  None])

learning_rate  =  tf.placeholder(tf.float32,  shape=())

W   =   tf.Variable(tf.zeros([1,  n_dim])) b     =     tf.Variable(tf.zeros(1))

init   =   tf.global_variables_initializer()

注意代码与上面的线性回归相同。但是我们必须定义不同的损失函数和不神经元输出 (sigmoid函数).

y_   =   tf.sigmoid(tf.matmul(W,X)+b)

cost  =  -  tf.reduce_mean(Y  *  tf.log(y_)+(1-Y)  *  tf.log(1-y_))

training_step    =    tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

我们用sigmoid函数作为神经元的输出,使用 tf.sigmoid(). 运行模型的代码与线性回归相同.我们只改变函数名称.

def   run_logistic_model(learning_r,   training_epochs,   train_obs, train_labels,  debug  =  False):

sess  =  tf.Session() sess.run(init)

cost_history  =  np.empty(shape=[0],  dtype  =  float)

for epoch in range(training_epochs+1):

sess.run(training_step,  feed_dict  =  {X:  train_obs,  Y:  train_labels, learning_rate:    learning_r})

cost_ = sess.run(cost, feed_dict={ X:train_obs, Y: train_labels, learning_rate:  learning_r})

cost_history  =  np.append(cost_history,  cost_)

if (epoch %  500 == 0) &  debug:

print("Reached epoch",epoch,"cost J =", str.format('{0:.6f}', cost_))

return sess, cost_history

我们运行模型并看一下结果.我们从学习速率0.01开始.

sess,  cost_history  =  run_logistic_model(learning_r  =  0.01,

training_epochs = 5000, train_obs  =  Xtrain, train_labels   =   ytrain, debug = True)

代码的输出如下 ( 3000 epochs后停止):

Reached epoch 0 cost J = 0.678598 Reached epoch 500 cost J = 0.108655 Reached epoch 1000 cost J = 0.078912 Reached epoch 1500 cost J = 0.066786 Reached epoch 2000 cost J = 0.059914 Reached epoch 2500 cost J = 0.055372 Reached epoch 3000 cost J = nan

发生什么了? 突然,某些点,我们的损失函数取nan (不是数字).看来模型在某个点工作得不好。如果学习速率太大,或初始化权重错误,你的值

yˆ(i )  = P (y(i )  = 1|x(i ) ) 或能接按于零或1 ( sigmoid函数取值接近 0 1 以于非常大的正或负的z值).记住,在损失函数里,你有两个项tf.log(y_) tf.log(1-y_), 因为 log函数对于值零没有定义,如果 y_ 0 1, 你会得到 nan, 因为代码试图评估tf.log(0).例如,我们可以运行模型使用学习速率 2.0.只要一个 epoch, 你的损失函数就得到nan值。很容易理解原因,如果你打印b在第一个训练步前后。简单的修改你的模型代码,使用下面的版本 :

def   run_logistic_model(learning_r,   training_epochs,   train_obs,   train_ labels,  debug  =  False):

sess  =  tf.Session() sess.run(init)

cost_history = np.empty(shape=[0], dtype = float) for epoch in range(training_epochs+1):

print ('epoch: ', epoch)

print(sess.run(b,  feed_dict={X:train_obs,  Y:  train_labels, learning_rate:   learning_r}))

sess.run(training_step,  feed_dict  =  {X:  train_obs,  Y:  train_labels, learning_rate:    learning_r})

print(sess.run(b,  feed_dict={X:train_obs,  Y:  train_labels, learning_rate:   learning_r}))

cost_ = sess.run(cost, feed_dict={ X:train_obs, Y: train_labels, learning_rate:  learning_r})

cost_history  =  np.append(cost_history,  cost_)

if (epoch %  500 == 0) &  debug:

print("Reached epoch",epoch,"cost J =", str.format('{0:.6f}', cost_))

return sess, cost_history

你得到下面的结果 (训练一个epoch):

epoch:    0

[ 0.]

[-0.05966223]

Reached epoch 0 cost J = nan epoch:      1

[-0.05966223]

[ nan]

你看到b0变到 -0.05966223然后再到 nan? 因此, z = wTX + b 这为 nan, 然后y = σ(z) 也变为 nan, 最后损失函数是 y的函数,结果为nan. 这是因为学习速率过大。解决方案呢? 你应该试试不同的学习速率 (更少的值).

我们试试并得到更稳定的结果,在 2500 epochs之后.我们运行模型:

sess,   cost_history   =   run_logistic_model(learning_r   =   0.005,

training_epochs = 5000, train_obs  =  Xtrain, train_labels   =   ytrain, debug = True)

输出如下

Reached epoch 0 cost J = 0.685799 Reached epoch 500 cost J = 0.154386 Reached epoch 1000 cost J = 0.108590 Reached epoch 1500 cost J = 0.089566 Reached epoch 2000 cost J = 0.078767 Reached epoch 2500 cost J = 0.071669 Reached epoch 3000 cost J = 0.066580 Reached epoch 3500 cost J = 0.062715 Reached epoch 4000 cost J = 0.059656 Reached epoch 4500 cost J = 0.057158 Reached epoch 5000 cost J = 0.055069

再也没有nan输出了。你可以在图 3-48看损失数.要评估我们的模型,我们必须选择优化量度 (如前所述).对于二分类问题,分类量度是准确率  (记为 a) 可以理解为结果与真实值的差的量度.数学上,它这样计算

要得到准确率,我们运行下面的代码. (记住 我们分类观察i为分类 0 如果 P(y(i) = 1| x(i)) < 0.5, 或者分类 1如果 P(y(i) = 1| x(i)) > 0.5.)

correct_prediction1   =   tf.equal(tf.greater(y_,   0.5),   tf.equal(Y,1)) accuracy  =  tf.reduce_mean(tf.cast(correct_prediction1,  tf.float32)) print(sess.run(accuracy,  feed_dict={X:Xtrain,  Y:  ytrain,  learning_rate: 0.05}))

使用这个模型,我们得到准确率为 98.6%. 这对于一个神经元的网络不差。

3-48. 损失函数与 epochs,学习速率为0.005

你可以运行前面的模型更多的epochs (使用学习速度为 0.005) 。你会发现,在7000 epochs,又出现 nan 。解决方案是减少学习速率增加 epochs数。简单的解决方案是,每 500 减半学习速率,就会消除 nans.后面详细讨论相似的方法.

你可以运行前面的模型更多的epochs (使用学习速度为 0.005) 。你会发现,在7000 epochs,又出现 nan 。解决方案是减少学习速率增加 epochs数。简单的解决方案是,每 500 减半学习速率,就会消除 nans.后面详细讨论相似的方法.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/914409.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/914409.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java设计模式之行为型模式(命令模式)介绍与说明

一、核心定义与目标 命令模式通过对象化请求&#xff0c;将操作的具体实现细节隐藏在命令对象中&#xff0c;使得调用者&#xff08;Invoker&#xff09;无需直接与接收者&#xff08;Receiver&#xff09;交互&#xff0c;仅需通过命令对象间接调用。这种解耦设计支持以下功能…

【深度学习新浪潮】xAI新发布的Grok4有什么看点?

Grok4作为马斯克旗下xAI公司最新发布的旗舰AI模型,其核心看点和评测要点可总结如下: 一、Grok4的核心看点 学术推理能力全面超越人类博士水平 在「人类终极考试」(HLE)中,Grok4基础版正确率达25.4%,启用工具后飙升至44.4%,远超Gemini 2.5 Pro(21.6%)和OpenAI o3(20.…

观成科技:基于自监督学习技术的恶意加密流量检测方案

1.前言当前&#xff0c;随着加密协议技术的广泛应用&#xff0c;互联网用户的个人流量隐私得到了有效保护&#xff0c;但与此同时也衍生出一系列安全问题。由于加密流量在传输过程中无法被解密&#xff0c;导致传输信息呈现“黑盒化”特征&#xff0c;这为恶意攻击者利用加密流…

通用定时器GPT

目录 GPT核心特性 GPT 计数器操作模式 重启模式 自由运行模式 GPT时钟源 GPT框图 输入捕获&#xff1a;测量外部信号的高电平脉冲宽度 输出比较&#xff1a;生成 1kHz PWM 波 GPT模块外部引脚复用与功能映射表 GPT使用注意事项 GPT Memory Map GPT寄存器 GPTx_CR寄存…

#oda0095. 字符串通配符【B卷 100分】-字符串

题目描述问题描述&#xff1a;在计算机中&#xff0c;通配符一种特殊语法&#xff0c;广泛应用于文件搜索、数据库、正则表达式等领域。现要求各位实现字符串通配符的算法。要求&#xff1a;实现如下2个通配符&#xff1a;* &#xff1a;匹配0个或以上的字符&#xff08;注&…

面向对象设计原则

面向对象&#xff1a;是一种编程思想&#xff0c;面向过程是关注实现的步骤&#xff0c;每个步骤定义一个函数&#xff0c;调用函数执行即可。面向对象关注的是谁来执行&#xff0c;把具有相同属性和行为的一类事物进行抽象成类&#xff0c;然后再通过实例化出一个个具体的对象…

Hyperledger Fabric深入解读:企业级区块链的架构、应用与未来

一、引言&#xff1a;企业级区块链的标杆Hyperledger Fabric是Linux基金会主导的开源项目&#xff0c;专为企业级应用设计&#xff0c;以模块化架构、许可链机制和隐私保护为核心&#xff0c;广泛应用于金融、供应链、医疗等领域。相较于公有链&#xff08;如以太坊&#xff09…

从0开始学习R语言--Day45--Hausman检验

当我们在探究数据本身是否和变量相关时&#xff0c;往往都会对这两者进行回归分析&#xff0c;控制一下变量来看看趋势走向。但其实在分析前&#xff0c;我们可以先尝试做Hausman检验&#xff0c;这可以帮助我们判断数据的变化到底是因为变量不一样了还是因为自己的个体效应所以…

闲庭信步使用图像验证平台加速FPGA的开发:第九课——图像插值的FPGA实现

&#xff08;本系列只需要modelsim即可完成数字图像的处理&#xff0c;每个工程都搭建了全自动化的仿真环境&#xff0c;只需要双击top_tb.bat文件就可以完成整个的仿真&#xff0c;大大降低了初学者的门槛&#xff01;&#xff01;&#xff01;&#xff01;如需要该系列的工程…

Android事件分发机制完整总结

一、核心概念事件分发的本质Android事件分发采用责任链模式&#xff0c;事件从Activity开始&#xff0c;依次经过ViewGroup和View。整个机制只有一个入口&#xff1a;dispatchTouchEvent方法。onInterceptTouchEvent和onTouchEvent都不是独立的事件入口&#xff0c;而是被dispa…

【论文阅读】AdaReasoner: Adaptive Reasoning Enables More Flexible Thinking

AdaReasoner: Adaptive Reasoning Enables More Flexible Thinking3. AdaReasoner3.1 动机3.2 问题定义3.3 动作选择过程3.3.1 动作空间定义3.3.2 动作选择3.4 探索策略3.5 强化学习训练3.5.1 训练算法3.5.2 目标函数3.5.3 损失函数AdaReasoner: Adaptive Reasoning Enables Mo…

深入了解Modbus TCP:工业通信的“通用语言”

目录 简介一、Modbus TCP的“前世今生”二、Modbus TCP的核心特点三、Modbus TCP的工作原理1. 报文结构2. 功能码四、Modbus TCP的应用场景五、使用Modbus TCP的注意事项六、总结简介 在工业自动化的世界里,不同设备之间的“对话”至关重要。从PLC(可编程逻辑控制器)到传感…

基于Selenium和FFmpeg的全平台短视频自动化发布系统

一、项目背景与概述在当今短视频营销盛行的时代&#xff0c;许多企业和个人需要同时管理多个短视频平台账号。手动上传视频到抖音、快手、小红书等平台不仅效率低下&#xff0c;而且容易出错。本文将介绍一个基于Python的自动化短视频处理与发布系统&#xff0c;它能够&#xf…

技术演进中的开发沉思-31 MFC系列:类层次结构

提及MFC&#xff0c;不得不说他的类层次。如果把 MFC 框架比作是座精密的钟表&#xff0c;那类层次结构便是其内部咬合的齿轮组。每个类都有明确的 “家族地位”&#xff0c;既继承着先辈的本领&#xff0c;又发展出独特的专长。这种层级分明的设计&#xff0c;让 Windows 编程…

2023.05.06 更新前端面试问题总结(12道题)

2023.05.04 - 2023.05.06 更新前端面试问题总结&#xff08;12道题&#xff09; 获取更多面试相关问题可以访问 github 地址: https://github.com/pro-collection/interview-question/issues gitee 地址: https://gitee.com/yanleweb/interview-question/issues 目录&#xff1…

【网络】Linux 内核优化实战 - net.ipv4.tcp_keepalive_intvl

目录1. TCP Keep-Alive 机制回顾2. 参数作用3. 参数取值与影响4. 使用场景与建议5. 相关参数6. 如何配置该参数临时生效&#xff08;重启后失效&#xff09;&#xff1a;永久生效&#xff08;需重启或重载配置&#xff09;&#xff1a;7. 性能优化建议8. 监控与故障排查net.ipv…

20250710解决KickPi的K7的SDK编译异常:rk3576-android14.0-25250704.tar.gz【降低BUILD_JOBS】

20250710解决KickPi的K7的SDK编译异常&#xff1a;rk3576-android14.0-25250704.tar.gz【降低BUILD_JOBS】 2025/7/10 20:59缘起&#xff1a;KickPi的K7的SDK编译异常&#xff1a;rk3576-android14.0-25250704.tar.gzZ:\14TB\SDK\rk3576_data\1-SDK软件源码\Android14\20250704…

《Java EE与中间件》实验一 基于MyBatis的留言本

目 录 一、实验目的和要求 1、实验目的 2、实验要求 二、实验实现思路及步骤 1、实验思路 2、实验步骤 3、实验方案 三、主要开发工具 四、实验效果及实现代码 1、留言本数据库构建实现 &#xff08;1&#xff09;建立javaee-project数据库 &#xff08;2&#xf…

ARM汇编编程(AArch64架构) - 第14课:安全扩展(ARM TrustZone)

目录1. TrustZone基础概念1.1 安全扩展架构1.2 关键组件2. 世界切换机制2.1 状态切换流程2.2 关键寄存器配置3. SMC调用实现3.1 调用规范3.2 完整调用流程4. 实战练习4.1 实验&#xff1a;实现双世界通信4.2 调试技巧1. TrustZone基础概念 1.1 安全扩展架构 startuml rectang…

OpenCV哈希算法------Marr-Hildreth 边缘检测哈希算法

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 该类实现了 Marr-Hildreth 边缘检测哈希算法&#xff08;Marr-Hildreth Hash&#xff09;&#xff0c;用于图像相似性比较。它基于 Marr-Hildreth …