逻辑斯蒂回归

逻辑斯蒂回归简介

  逻辑斯蒂回归(Logistic Regression)是一个非常经典的算法,虽然被称为回归,但其实际上是分类模型,并常用于二分类。因为通过逻辑回归模型,我们得到的计算结果是0-1之间的连续数字,可以把它称为“可能性”(概率),然后,给这个可能性加一个阈值,就成了分类。逻辑回归因其简单、可并行化、可解释强深受工业界喜爱。
  Logistic 回归的本质是:假设数据服从这个分布,然后使用极大似然估计做参数的估计。

逻辑回归拟合函数

  逻辑回归算法的拟合函数,叫做Sigmoid函数,是一个单调可导的函数,通过设置阈值0.5,就可以分为两类
y ^ = { 1 , σ ( x ) > 0.5 0 , σ ( x ) ≤ 0.5 \hat{y} = \begin{cases} 1, & \sigma(x) > 0.5 \\ 0, & \sigma(x) \leq 0.5 \\ \end{cases} y^={1,0,σ(x)>0.5σ(x)0.5
请添加图片描述

从图形上看,sigmoid曲线就像是被掰弯捋平后的线性回归直线,将取值范围(−∞,+∞)映射到(0,1) 之间,更适宜表示预测的概率,即事件发生的“可能性” 。

Sigmoid函数的输入记为 z z z,多元场景下的公式为: z = w 0 x 0 + w 1 x 1 + w 2 x 2 + . . . + w n x n z = w_0x_0 + w_1x_1 + w_2x_2 + ... + w_nx_n z=w0x0+w1x1+w2x2+...+wnxn,采用向量的写法 z = x w z = xw z=xw,其中 w 0 w_0 w0是多元函数常数项,而 x 0 x_0 x0的值置为1,便于与 w w w矩阵相乘。
f ( x ) = 1 1 + e − x w f(x)=\frac{1}{1+e^{-xw}} f(x)=1+exw1

最大似然函数估计

在二分类问题中,y只取0或1,可以组合起来表示y的概率:
P ( y ) = P ( y = 1 ) y P ( y = 0 ) 1 − y P(y) = P(y=1)^yP(y=0)^{1-y} P(y)=P(y=1)yP(y=0)1y

加上特征 x x x和参数 w w w后,表示为:
P ( y ∣ x , w ) = P ( y = 1 ∣ x , w ) y [ 1 − P ( y = 1 ∣ x , w ) ] 1 − y P(y|x,w) = P(y=1|x,w)^y[1 - P(y=1|x,w)]^{1-y} P(yx,w)=P(y=1∣x,w)y[1P(y=1∣x,w)]1y

P ( y = 1 ∣ x , w ) = 1 1 + e − x w P(y=1|x,w)=\frac{1}{1+e^{-xw}} P(y=1∣x,w)=1+exw1代入上式得:
P ( y ∣ x , w ) = ( 1 1 + e − x w ) y ( 1 − 1 1 + e − x w ) 1 − y P(y|x,w) = (\frac{1}{1+e^{-xw}})^y(1 - \frac{1}{1+e^{-xw}})^{1-y} P(yx,w)=(1+exw1)y(11+exw1)1y

( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x n , y n ) (x_1,y_1),(x_2,y_2),...,(x_n,y_n) (x1,y1),(x2,y2),...,(xn,yn)是实际观测的数据,而不同事件是相互独立的,那么它们同时发生的概率为 ∏ i = 1 n P ( y i ∣ x i , w ) \prod_{i=1}^nP(y_i|x_i,w) i=1nP(yixi,w)。即似然函数为:
L ( w ) = ∏ i = 1 n P ( y i ∣ x i , w ) = ∏ i = 1 n ( 1 1 + e − x i w ) y i ( 1 − 1 1 + e − x i w ) 1 − y i L(w) = \prod_{i=1}^nP(y_i|x_i,w)=\prod_{i=1}^n(\frac{1}{1+e^{-x_iw}})^{y_i}(1 - \frac{1}{1+e^{-x_iw}})^{1-y_i} L(w)=i=1nP(yixi,w)=i=1n(1+exiw1)yi(11+exiw1)1yi
如此,问题变为了参数 w w w在取什么值时, L ( w ) L(w) L(w)取得极大值。
w ^ = a r g m a x w L ( w ) \hat{w}=arg\ \underset{w}{max} \ L(w) w^=arg wmax L(w)

交叉熵损失函数

  损失函数是用于衡量预测值与实际值的偏离程度,即模型预测的错误程度。也就是说,这个值越小,认为模型效果越好,举个极端例子,如果预测完全精确,则损失函数值为0。
  我们要做的是 L ( w ) L(w) L(w)取得极大值,反过来 − L ( w ) -L(w) L(w)取得极小值,与损失函数的要求相同。因连乘不易取极值,需对 L ( w ) L(w) L(w)取对数后,在取相反数,这样就成为了交叉熵损失函数:
J ( w ) = − log ⁡ L ( w ) = − ∑ i = 1 n [ y i log ⁡ P ( y i ) + ( 1 − y i ) log ⁡ ( 1 − P ( y i ) ) ] J(w)=-\log L(w)=-\sum_{i=1}^n[y_i\log{P(y_i)}+(1-y_i)\log (1-P(y_i))] J(w)=logL(w)=i=1n[yilogP(yi)+(1yi)log(1P(yi))]
其中:
y i y_i yi : 表示样本 i i i的标记(label),正类为1,负类为0
P ( y i ) P(y_i) P(yi):表示样本 i i i预测为正类的概率

梯度下降法求解

对于Sigmoid函数 f ( z ) = 1 1 + e − z f(z)=\frac{1}{1+e^{-z}} f(z)=1+ez1,求导得:
f ′ ( z ) = ( 1 1 + e − z ) ′ = − ( e − z ) ′ ( 1 + e − z ) 2 = e − z ( 1 + e − z ) 2 f^\prime(z) = (\frac{1}{1+e^{-z}})^\prime=-\frac{(e^{-z})^\prime}{(1+e^{-z})^2}=\frac{e^{-z}}{(1+e^{-z})^2} f(z)=(1+ez1)=(1+ez)2(ez)=(1+ez)2ez

这还不算完,我们发现 1 − f ( z ) = e − z 1 + e − z 1-f(z)=\frac{e^{-z}}{1+e^{-z}} 1f(z)=1+ezez,而 f ′ ( z ) f^\prime(z) f(z)正好可以拆分为 e − z 1 + e − z ⋅ 1 1 + e − z \frac{e^{-z}}{1+e^{-z}} \cdot \frac{1}{1+e^{-z}} 1+ezez1+ez1,也就是说:
f ′ ( z ) = f ( z ) ⋅ ( 1 − f ( z ) ) f^\prime(z)=f(z)\cdot(1-f(z)) f(z)=f(z)(1f(z))

已知 z = x w z=xw z=xw,而 x x x是实际观测数据,未知的是 w w w,所以后面是对 w w w求导,记:
∂ J ( w ) ∂ w = ∂ J ( w ) ∂ f ( z ) ∗ ∂ f ( z ) ∂ z ∗ ∂ z ∂ w \frac{\partial J(w)}{\partial w}=\frac{\partial J(w)}{\partial f(z)} * \frac{\partial f(z)}{\partial z} * \frac{\partial z}{\partial w} wJ(w)=f(z)J(w)zf(z)wz

其中:
∂ J ( w ) ∂ f ( z ) = − [ y log ⁡ f ( z ) + ( 1 − y ) log ⁡ ( 1 − f ( z ) ) ] ′ = − ( y f ( z ) + ( 1 − y ) − 1 1 − f ( z ) ) = − ( y f ( z ) + y − 1 1 − f ( z ) ) \begin{aligned}\frac{\partial J(w)}{\partial f(z)} &= -[y \log f(z) + (1-y)\log (1-f(z))]^\prime \\ &= -( \frac{y} {f(z)} + (1-y) \frac{-1} {1-f(z)}) \\ &= -( \frac{y} {f(z)} + \frac{y-1} {1-f(z)}) \\ \end{aligned} f(z)J(w)=[ylogf(z)+(1y)log(1f(z))]=(f(z)y+(1y)1f(z)1)=(f(z)y+1f(z)y1)

∂ f ( z ) ∂ z = f ( z ) ( 1 − f ( z ) ) \begin{aligned}\frac{\partial f(z)}{\partial z}&=f(z)(1-f(z)) \end{aligned} zf(z)=f(z)(1f(z))

∂ z ∂ w = x \begin{aligned} \frac{\partial z}{\partial w} &= x\end{aligned} wz=x

综上所得:
∂ J ( w ) ∂ w = − ( y f ( z ) + y − 1 1 − f ( z ) ) ∗ f ( z ) ( 1 − f ( z ) ) ∗ x = − ( y − f ( z ) ) ∗ x = − ( y − 1 1 + e − x w ) ∗ x \begin{aligned}\frac{\partial J(w)}{\partial w} &=-( \frac{y} {f(z)} + \frac{y-1} {1-f(z)}) *f(z)(1-f(z)) * x \\ &=-(y-f(z))*x \\ &= - (y-\frac{1}{1+e^{-xw}}) * x \end{aligned} wJ(w)=(f(z)y+1f(z)y1)f(z)(1f(z))x=(yf(z))x=(y1+exw1)x

因此,梯度上升迭代公式为:
w : = w + α ( y − 1 1 + e − x w ) ∗ x w:= w +\alpha(y-\frac{1}{1+e^{-xw}})*x w:=w+α(y1+exw1)x

梯度下降算法过程:

  1. 初始化 w w w向量的值,即 Θ 0 \Theta_{0} Θ0,将其代入G得到当前位置的梯度;
  2. 用步长α乘以当前梯度,得到从当前位置下降的距离;
  3. 更新 Θ 1 \Theta_1 Θ1,其更新表达式为 Θ 1 = Θ 0 − α G \Theta_1=\Theta_0-\alpha G Θ1=Θ0αG
  4. 重复以上步骤,直到更新到某个 Θ k \Theta_k Θk,达到停止条件,这个 Θ k \Theta_k Θk就是我们求解的参数向量。

逻辑斯蒂回归分布

定义:设X是连续随机变量,X服从逻辑斯蒂分布是指X具有下列分布函数和密度函数:
F ( x ) = P ( X ≤ x ) = 1 1 + e − ( x − μ ) / γ F(x)=P(X \leq x)=\frac{1}{1+e^{-(x-\mu)/\gamma}} F(x)=P(Xx)=1+e(xμ)/γ1

f ( x ) = F ′ ( x ) = e − ( x − μ ) / γ γ ( 1 + e − ( x − μ ) / γ ) 2 f(x)=F'(x)=\frac{e^{-(x-\mu)/\gamma}}{\gamma(1+e^{-(x-\mu)/\gamma})^2} f(x)=F(x)=γ(1+e(xμ)/γ)2e(xμ)/γ

式中, μ \mu μ为位置参数, γ > 0 \gamma>0 γ>0为形状参数。

Logistic 分布是由其位置和尺度参数定义的连续分布。Logistic 分布的形状与正态分布的形状相似,但是 Logistic 分布的尾部更长,所以我们可以使用 Logistic 分布来建模比正态分布具有更长尾部和更高波峰的数据分布。在深度学习中常用到的 S i g m o i d Sigmoid Sigmoid函数就是 Logistic 的分布函数在 μ = 0 , γ = 1 \mu=0,\gamma=1 μ=0,γ=1的特殊形式。

逻辑斯蒂回归实战

首先,下载数据集 testSet.txt,数据集链接:https://pan.baidu.com/s/1rJm0Ok_9OfrsEktVqhGoCQ?pwd=47db ,提取码:47db

from numpy import *# 加载数据集
def loadDataSet():datas = []; classLabels = []fr = open('testSet.txt')for line in fr.readlines():lineArr = line.strip().split()datas.append([1.0, float(lineArr[0]), float(lineArr[1])])classLabels.append(int(lineArr[2]))return datas,classLabelsdef sigmoid(inX):return 1.0/(1+exp(-inX))# return 0.5 * (1 + tanh(0.5 * inX))# 梯度上升算法
def gradAscent(datas, classLabels):dataMat = mat(datas)             #convert to NumPy matrixlabelMat = mat(classLabels).transpose() #convert to NumPy matrixm,n = shape(dataMat)alpha = 0.001  # 步长maxCycles = 500  # 迭代次数weights = ones((n,1))for k in range(maxCycles):       #heavy on matrix operationsh = sigmoid(dataMat*weights) #matrix mult,h为列向量,元素数为nerror = (labelMat - h)       #vector subtractionweights = weights + alpha * dataMat.transpose()* error #matrix multreturn weights# 画出数据集和逻辑回归最佳拟合直线
def plotBestFit(weights):import matplotlib.pyplot as pltdataMat,labelMat=loadDataSet()dataArr = array(dataMat)n = shape(dataArr)[0] xcord1 = []; ycord1 = []xcord2 = []; ycord2 = []for i in range(n):if int(labelMat[i])== 1:xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])else:xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])fig = plt.figure()ax = fig.add_subplot(111)ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')ax.scatter(xcord2, ycord2, s=30, c='green')x = arange(-3.0, 3.0, 0.1)y = (-weights[0]-weights[1]*x)/weights[2]ax.plot(x, y.T)plt.xlabel('X1'); plt.ylabel('X2')plt.show()# 训练梯度下降算法并画出最佳拟合直线
datas,classLabels = loadDataSet()
weights = gradAscent(datas, classLabels)
plotBestFit(weights)

请添加图片描述

从疝气病症预测病马的死亡率

疝病是描述马胃肠痛的术语,数据集中包含368个样本和28个特征。使用Logistic回归估计马疝病的死亡率步骤如下:

  1. 收集数据:给定数据文件。
  2. 准备数据:用Python解析文本文件并填充缺失值。
  3. 分析数据:可视化并观察数据。
  4. 训练算法:使用优化算法,找到最佳的系数。
  5. 测试算法:为了量化回归的效果,需要观察错误率。根据错误率决定是否回退到训练阶段,通过改变迭代的次数和步长等参数来得到更好的回归系数。
  6. 使用算法:实现一个简单的命令行程序来收集马的症状并输出预测结果。

需要说明的是,除了部分指标主观和难以测量外,该数据存在的另一个问题是大约30%的值是缺失的。一些可选的处理缺失值的做法有:

  • 使用可用特征的均值来填补缺失值
  • 使用特殊值来填补缺失值,如-1
  • 忽略有缺失值的样本
  • 使用相似样本的均值填补缺失值
  • 使用另外的机器学习算法预测缺失值

这里,选择实数0来替换所有缺失值,这样在更新系数时,0值不会有影响,而且对结果的预测不具有任何倾向性。若类别标签缺失则直接丢弃。原始数据集经过预处理后保存成两个文件:horseColicTest.txt 和 horseColicTraining.txt。

from numpy import *def sigmoid(inX):return 0.5 * (1 + tanh(0.5 * inX))# 随机梯度上升算法
def stocGradAscent0(datas, classLabels):m,n = shape(datas)alpha = 0.01weights = ones(n)   #initialize to all onesfor i in range(m):h = sigmoid(sum(datas[i]*weights))error = classLabels[i] - hweights = weights + alpha * error * datas[i]return weights# 改进的随机梯度上升算法
def stocGradAscent1(datas, classLabels, numIter=150):m,n = shape(datas)weights = ones(n)   #initialize to all onesfor j in range(numIter):dataIndex = list(range(m))for i in range(m):alpha = 4/(1.0+j+i)+0.0001    #apha decreases with iteration, does not randIndex = int(random.uniform(0,len(dataIndex)))#go to 0 because of the constanth = sigmoid(sum(datas[randIndex]*weights))error = classLabels[randIndex] - hweights = weights + alpha * error * datas[randIndex]del(dataIndex[randIndex])return weights# 逻辑回归分类函数
def classifyVector(inX, weights):prob = sigmoid(sum(inX*weights))if prob > 0.5: return 1.0else: return 0.0def colicTest():frTrain = open('horseColicTraining.txt'); frTest = open('horseColicTest.txt')trainingSet = []; trainingLabels = []for line in frTrain.readlines():currLine = line.strip().split('\t')lineArr =[]for i in range(21):lineArr.append(float(currLine[i]))trainingSet.append(lineArr)trainingLabels.append(float(currLine[21]))trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 1000)errorCount = 0; numTestVec = 0.0for line in frTest.readlines():numTestVec += 1.0currLine = line.strip().split('\t')lineArr =[]for i in range(21):lineArr.append(float(currLine[i]))if int(classifyVector(array(lineArr), trainWeights))!= int(currLine[21]):errorCount += 1errorRate = (float(errorCount)/numTestVec)print ("the error rate of this test is: %f" % errorRate)return errorRatedef multiTest():numTests = 10; errorSum=0.0for k in range(numTests):errorSum += colicTest()print ("after %d iterations the average error rate is: %f" % (numTests, errorSum/float(numTests)))# 训练并检验
multiTest()

the error rate of this test is: 0.358209
the error rate of this test is: 0.328358
the error rate of this test is: 0.283582
the error rate of this test is: 0.388060
the error rate of this test is: 0.313433
the error rate of this test is: 0.268657
the error rate of this test is: 0.283582
the error rate of this test is: 0.358209
the error rate of this test is: 0.388060
the error rate of this test is: 0.283582
after 10 iterations the average error rate is: 0.325373

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

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

相关文章

【Android Studio】在单独的窗口中启动模拟器

参考:https://developer.android.com/studio/run/emulator-launch-separate-window?hlzh-cn 默认情况下,Android 模拟器会在 Android Studio 中运行。这样,您就可以高效地使用屏幕空间,使用热键在模拟器和编辑器窗口之间快速导航…

03 decision tree(决策树)

一、decision tree(决策树) 1. classification problems(纯度) i . entropy (熵) ​ 作用:衡量一组数据的纯度是否很纯 ,当五五开时他的熵都是最高的,当全是或者都不是…

Guava Cache 异步刷新技巧,你值得拥有!

以下文章来源于勇哥Java实战 ,作者勇哥 Guava Cache是一款非常优秀的本地缓存框架。 这篇文章,我们聊聊如何使用 Guava Cache 异步刷新技巧带飞系统性能 。 1 经典配置 Guava Cache 的数据结构跟 JDK1.7 的 ConcurrentHashMap 类似,提供了基…

【机器学习前置知识】Beta分布

Beta分布与二项分布的关系 Beta分布与二项分布密切相关,由二项分布扩展而来,它是用来描述一个连续型随机变量出现的概率的概率密度分布,表示为 X X X~ B e t a ( a , b ) Beta(a,b) Beta(a,b) , a 、 b a、b a、b 是形状参数。B…

ES6之Proxy详解

✨ 专栏介绍 在现代Web开发中,JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性,还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言,JavaScript具有广泛的应用场景&#x…

P11 FFmpe时间基和时间戳

前言 从本章开始我们将要学习嵌入式音视频的学习了 ,使用的瑞芯微的开发板 🎬 个人主页:ChenPi 🐻推荐专栏1: 《C_ChenPi的博客-CSDN博客》✨✨✨ 🔥 推荐专栏2: 《Linux C应用编程(概念类)_C…

力扣1944.队列中可以看到的人数--单调栈

思路: 由题知一个人能 看到 他右边另一个人的条件是这两人之间的所有人都比他们两人 矮 ,也就是说,在自己右边第一个比自己高的人后面的人就肯定看不到了那么只需要找到右边第一个比自己高的人与自己之间的所有满足要求的人就行了&#xff0…

mysql保姆安装教程

前言:考完研回来,重新配置数据库的相关环境,按照本方法安装请确保你之前的MySQL已完全清除干净。 一.下载install文件 1.进入Mysql官网,点击下载 2.选择MySQL Installer for Windows 3.推荐选择第二个安装包 4.不登陆&#xff0c…

23 导航栏

效果演示 实现了一个响应式的导航栏&#xff0c;当鼠标悬停在导航栏上的某个选项上时&#xff0c;对应的横条会从左到右地移动&#xff0c;从而实现了导航栏的动态效果。 Code <div class"flex"><ul><li>1</li><li>2</li><l…

怎么快速修复mfc140.dll文件?解决mfc140.dll缺失的方法

面对计算机报告的 ​mfc140.dll​ 文件遗失错误&#xff0c;这通常表明系统中缺少一个关键的动态链接库文件&#xff0c;该文件对于运行以 Microsoft Foundation Class (MFC) 库编写的程序十分重要&#xff0c;尤其是那些需要图形界面的应用程序和一些游戏。若没有这个文件&…

【AI视野·今日Robot 机器人论文速览 第六十六期】Tue, 31 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Tue, 31 Oct 2023 Totally 39 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers DEFT: Dexterous Fine-Tuning for Real-World Hand Policies Authors Aditya Kannan, Kenneth Shaw, Shikhar Bahl, Pragna Ma…

【Minikube Prometheus】基于Prometheus Grafana监控由Minikube创建的K8S集群

文章目录 1. 系统信息参数说明2. Docker安装3. minikube安装4. kubectl安装5. Helm安装6. 启动Kubernetes集群v1.28.37. 使用helm安装Prometheus8. 使用helm安装Grafana9. Grafana的Dashboard设定10. 设定Prometheus数据源11. 导入Kubernetes Dashboard12. 实验过程中的常见问题…

软件设计模式 --- 类,对象和工厂模式的引入

Q1&#xff1a;什么是软件设计模式&#xff1f; A&#xff1a;软件设计模式&#xff0c;又称设计模式。它是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。综上&…

vmware安装redhat 7.6 操作系统

vmware安装redhat 7.6 操作系统 1、下载redhat 7.6 操作系统镜像文件2、安装redhat 7.6操作系统3、配置redhat 7.6 操作系统3.1、配置静态IP地址 和 dns3.2、查看磁盘分区3.3、查看系统版本 1、下载redhat 7.6 操作系统镜像文件 链接: 盘盘 zwzg 文件名&#xff1a;rhel-serv…

JVM 常用知识和面试题

1. 什么是JVM内存结构&#xff1f; jvm将虚拟机分为5大区域&#xff0c;程序计数器、虚拟机栈、本地方法栈、java堆、方法区&#xff1b; 程序计数器&#xff1a;线程私有的&#xff0c;是一块很小的内存空间&#xff0c;作为当前线程的行号指示器&#xff0c;用于记录当前虚拟…

LeetCode-无重复字符的最长子串(3)

题目描述&#xff1a; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 代码&#xff1a; class Solution {public int lengthOfLongestSubstring(String s) {Set<Character> occnew HashSet<Character>();int lens.length();int…

OpenCASCADE MFC例子

OpenCASCADE MFC例子 说明 一直对OpenCASCADE一直都比较感兴趣&#xff0c;这个例子是我参考这位大神C幼儿园中班小朋友的专栏做出来的OpenCASCADE_C幼儿园中班小朋友的博客-CSDN博客 不过我用的是vcpkg的方式安装OpenCASCADE&#xff0c;这个需要注意一下&#xff0c;可能需…

HackTheBox - Medium - Linux - Awkward

Awkward Awkward 是一款中等难度的机器&#xff0c;它突出显示了不会导致 RCE 的代码注入漏洞&#xff0c;而是 SSRF、LFI 和任意文件写入/追加漏洞。此外&#xff0c;该框还涉及通过不良的密码做法&#xff08;例如密码重用&#xff09;以及以纯文本形式存储密码来绕过身份验…

Mybatis缓存实现方式

文章目录 装饰器模式Cache 接口及核心实现Cache 接口装饰器1. BlockingCache2. FifoCache3. LruCache4. SoftCache5. WeakCache 小结 缓存是优化数据库性能的常用手段之一&#xff0c;我们在实践中经常使用的是 Memcached、Redis 等外部缓存组件&#xff0c;很多持久化框架提供…

【物联网】手把手完整实现STM32+ESP8266+MQTT+阿里云+APP应用——第3节-云产品流转配置

&#x1f31f;博主领域&#xff1a;嵌入式领域&人工智能&软件开发 本节目标&#xff1a;本节目标是进行云产品流转配置为后面实际的手机APP的接入做铺垫。云产品流转配置的目的是为了后面能够让后面实际做出来的手机APP可以控制STM32/MCU&#xff0c;STM32/MCU可以将数…