当前位置: 首页 > news >正文

西瓜书第三章

广义线性模型
考虑单点可微函数 g ( ⋅ ) g(\cdot) g(),令 y = g − 1 ( ω T x + b ) y=g^{-1}(\omega^{T}x+b) y=g1(ωTx+b),这样得到的模型称为“广义线性模型”,其中函数 g ( ⋅ ) g(\cdot) g()称为“联系函数”。显然,对数线性回归是广义线性模型在 g ( ⋅ ) = ln ⁡ ( ⋅ ) g(\cdot)=\ln (\cdot) g()=ln()时的特例。

对数几率回归

在线性回归模型的基础上,改进以完成分类任务。关键在于寻找一个单调可微函数,将分类任务的真实标记 y y y与线性回归模型的预测值联系起来。
考虑二分类任务
y ∈ { 0 , 1 } ⇔ z = ω T x + b y\in \{0,1\}\Leftrightarrow z=\omega^Tx+b y{0,1}z=ωTx+b
于是,我们需将实值z转换为0/1值。

  1. 单位跃阶函数:
    y = { 0 , z < 0 0.5 , z = 0 1 , z > 0 y= \left\{ \begin{aligned} 0,\quad z<0\\ 0.5,\quad z=0\\ 1,\quad z>0 \end{aligned} \right. y= 0,z<00.5,z=01,z>0
    单位跃阶函数不连续,从而不可微,故不能直接作为联系函数。
  2. 对数几率函数
    y = 1 1 + e − z y=\frac{1}{1+e^{-z}} y=1+ez1
    对数几率函数是一种Sigmoid函数。
    Sigmoid函数即形似S的函数,对率函数是Sigmoid函数最重要代表。
    在这里插入图片描述

代入广义线性模型中得到
y = 1 1 + e − ( ω T x + b ) = e ω T x + b 1 + e ω T x + b 1 − y = e − ( ω T x + b ) 1 + e − ( ω T x + b ) = 1 1 + e ω T x + b y 1 − y = e ω T x + b ln ⁡ y 1 − y = ω T x + b \begin{aligned} &y=\frac{1}{1+e^{-(\omega^{T}x+b)}}=\frac{e^{\omega^Tx+b}}{1+e^{\omega^Tx+b}} \\ &1-y=\frac{e^{-(\omega^Tx+b)}}{1+e^{-(\omega^Tx+b)}}=\frac{1}{1+e^{\omega^Tx+b}}\\ &\frac{y}{1-y}=e^{\omega^Tx+b}\\ &\ln \frac{y}{1-y}=\omega^Tx+b \end{aligned} y=1+e(ωTx+b)1=1+eωTx+beωTx+b1y=1+e(ωTx+b)e(ωTx+b)=1+eωTx+b11yy=eωTx+bln1yy=ωTx+b
若将y视为样本x作为正例的可能性,则1-y为样本x为反例的可能性,两者的比值 y 1 − y \frac{y}{1-y} 1yy称为“几率”,反映了样本x作为正例的可能性。对几率取对数则得到“对数几率”: ln ⁡ y 1 − y \ln \frac{y}{1-y} ln1yy
l n y 1 − y = ω T x + b ln \frac{y}{1-y}=\omega^Tx+b ln1yy=ωTx+b
实际上是用线性回归模型的预测结果去逼近真实的对数几率,因此该模型也称为“对数几率回归”。(虽然名字叫做回归,但实际上是一种分类学习方法

对数几率回归的优点

  1. 它是直接对分类的可能性进行建模,无需事先假设数据的分布,这样就避免了假设分布不准确所带来的问题。
  2. 它不仅预能预测出类别,而是可以得到近似概率预测,这对许多需要利用概率辅助决策的任务很有用。
  3. 对率函数是任意阶可导的凸函数,有很好的数学性质,现有的很多数值优化算法都可以直接用于求取最优解。

求解对率回归模型中的参数
将y视为类后验概率估计 p ( y = 1 ∣ x ) p(y=1|x) p(y=1∣x),则对率函数可重写为 ln ⁡ p ( y = 1 ∣ x ) p ( y = 0 ∣ x ) = ω T x + b \ln \frac{p(y=1|x)}{p(y=0|x)}=\omega^Tx+b lnp(y=0∣x)p(y=1∣x)=ωTx+b
由于 p ( y = 1 ∣ x ) + p ( y = 0 ∣ x ) = 1 p(y=1|x)+p(y=0|x)=1 p(y=1∣x)+p(y=0∣x)=1,从而有 y = p ( y = 1 ∣ x ) = e ω T x + b 1 + e ω T x + b 1 − y = p ( y = 0 ∣ x ) = 1 1 + e ω T x + b \begin{aligned} y=p(y=1|x)=\frac{e^{\omega^Tx+b}}{1+e^{\omega^Tx+b}} \\ 1-y=p(y=0|x)=\frac{1}{1+e^{\omega^Tx+b}} \end{aligned} y=p(y=1∣x)=1+eωTx+beωTx+b1y=p(y=0∣x)=1+eωTx+b1于是可以通过极大似然法来估计 ω \omega ω b b b。给定数据集 { ( x i , y i ) } i = 1 m \{(x_i,y_i)\}_{i=1}^m {(xi,yi)}i=1m,对率回归模型最大化“对数似然”
l ( ω ; b ) = ∑ i = 1 m ln ⁡ p ( y i ∣ x i ; ω , b ) l(\omega;b)=\sum_{i=1}^m{\ln p(y_i|x_i;\omega,b)} l(ω;b)=i=1mlnp(yixi;ω,b)即令每个样本属于其真实标记的概率越大越好。为了便于讨论,令 β = ( ω ; b ) , x ^ = ( x ; 1 ) \beta=(\omega;b),\quad \hat{x}=(x;1) β=(ω;b),x^=(x;1),则 ω T x + b \omega^Tx+b ωTx+b可以简写为 β T x ^ \beta^T\hat{x} βTx^。再令 p 1 ( x ^ ; β ) = p ( y = 1 ∣ x ^ ; β ) , p 0 ( x ^ ; β ) = p ( y = 0 ∣ x ^ ; β ) = 1 − p 1 ( x ^ ; β ) p_1(\hat{x};\beta)=p(y=1|\hat{x};\beta),p_0(\hat{x};\beta)=p(y=0|\hat{x};\beta)=1-p_1(\hat{x};\beta) p1(x^;β)=p(y=1∣x^;β),p0(x^;β)=p(y=0∣x^;β)=1p1(x^;β),则上式中的似然项可重写为 p ( y i ∣ x i ; ω , b ) = y i p 1 ( x ^ i ; β ) + ( 1 − y i ) p 0 ( x ^ i ; β ) p(y_i|x_i;\omega,b)=y_ip_1(\hat{x}_i;\beta)+(1-y_i)p_0(\hat{x}_i;\beta) p(yixi;ω,b)=yip1(x^i;β)+(1yi)p0(x^i;β),进一步代入得
l ( ω ; b ) = ∑ i = 1 m ln ⁡ [ y i p 1 ( x ^ i ; β ) + ( 1 − y i ) p 0 ( x ^ i ; β ) ] = ∑ i = 1 m ln ⁡ [ y i e ω T x i + b 1 + e ω T x i + b + ( 1 − y i ) 1 1 + e ω T x i + b ] = ∑ i = 1 m ln ⁡ [ y i e β T x ^ i 1 + e β T x ^ i + ( 1 − y i ) 1 1 + e β T x ^ i ] = ∑ i = 1 m ln ⁡ [ y i e β T x ^ i − y i + 1 1 + e β T x ^ i ] = ∑ i = 1 m [ ln ⁡ ( y i e β T x ^ i − y i + 1 ) − ln ⁡ ( 1 + e β T x ^ i ) ] = ∑ y i = 0 − ln ⁡ ( 1 + e β T x ^ i ) + ∑ y i = 1 [ ln ⁡ ( e β T x ^ i ) − ln ⁡ ( 1 + e β T x ^ i ) ] = − ∑ y i = 0 ln ⁡ ( 1 + e β T x ^ i ) + ∑ y i = 1 [ β T x ^ i − ln ⁡ ( 1 + e β T x ^ i ) ] = ∑ i = 1 m [ y i β T x ^ i − ln ⁡ ( 1 + e β T x ^ i ) ] \begin{aligned} l(\omega;b)&=\sum_{i=1}^m{\ln \left[ y_ip_1(\hat{x}_i;\beta)+(1-y_i)p_0(\hat{x}_i;\beta)\right]}\\ &=\sum_{i=1}^m{\ln \left[y_i\frac{e^{\omega^Tx_i+b}}{1+e^{\omega^Tx_i+b}}+(1-y_i)\frac{1}{1+e^{\omega^Tx_i+b}}\right]}\\ &=\sum_{i=1}^m{\ln \left[y_i\frac{e^{\beta^T\hat{x}_i}}{1+e^{\beta^T\hat{x}_i}}+(1-y_i)\frac{1}{1+e^{\beta^T\hat{x}_i}}\right]}\\ &=\sum_{i=1}^m{\ln \left[\frac{y_ie^{\beta^T\hat{x}_i}-y_i+1}{1+e^{\beta^T\hat{x}_i}}\right]}\\ &=\sum_{i=1}^m{\left[\ln (y_ie^{\beta^T\hat{x}_i}-y_i+1)-\ln (1+e^{\beta^T\hat{x}_i})\right]}\\ &=\sum_{y_i=0}{-\ln (1+e^{\beta^T\hat{x}_i})}+\sum_{y_i=1}{\left[\ln(e^{\beta^T\hat{x}_i})-\ln(1+e^{\beta^T\hat{x}_i})\right]}\\ &=-\sum_{y_i=0}{\ln (1+e^{\beta^T\hat{x}_i})}+\sum_{y_i=1}{\left[\beta^T\hat{x}_i-\ln(1+e^{\beta^T\hat{x}_i})\right]}\\ &=\sum_{i=1}^m{\left[y_i\beta^T\hat{x}_i-\ln(1+e^{\beta^T\hat{x}_i})\right]} \end{aligned} l(ω;b)=i=1mln[yip1(x^i;β)+(1yi)p0(x^i;β)]=i=1mln[yi1+eωTxi+beωTxi+b+(1yi)1+eωTxi+b1]=i=1mln[yi1+eβTx^ieβTx^i+(1yi)1+eβTx^i1]=i=1mln[1+eβTx^iyieβTx^iyi+1]=i=1m[ln(yieβTx^iyi+1)ln(1+eβTx^i)]=yi=0ln(1+eβTx^i)+yi=1[ln(eβTx^i)ln(1+eβTx^i)]=yi=0ln(1+eβTx^i)+yi=1[βTx^iln(1+eβTx^i)]=i=1m[yiβTx^iln(1+eβTx^i)]
从而最大化 l ( ω ; b ) l(\omega;b) l(ω;b)等价于最小化
l ( β ) = ∑ i = 1 m ( − y i β T x ^ i + ln ⁡ ( 1 + e β T x ^ i ) ) l(\beta)=\sum_{i=1}^m{\left(-y_i\beta^T\hat{x}_i+\ln(1+e^{\beta^T\hat{x}_i})\right)} l(β)=i=1m(yiβTx^i+ln(1+eβTx^i)) l ( β ) l(\beta) l(β)是关于 β \beta β的高阶可导函数,根据凸优化理论,经典的数值优化方法如梯度下降法、牛顿法等都可求得其最优解,于是就得到 β ∗ = a r g m i n β l ( β ) \beta^*=argmin_{\beta}l(\beta) β=argminβl(β)
例如牛顿法,其第t+1次轮迭代解的更新公式为
β t + 1 = β t − ( ∂ 2 l ( β ) ∂ β ∂ β T ) − 1 ∂ l ( β ) ∂ β \beta^{t+1}=\beta^{t}-{\left(\frac{\partial^2l(\beta)}{\partial\beta\partial\beta^T}\right)^{-1}\frac{\partial l(\beta)}{\partial\beta}} βt+1=βt(ββT2l(β))1βl(β)
其中关于 β \beta β的一阶、二阶导数分别为
∂ l ( β ) ∂ β = − ∑ i = 1 m x ^ i ( y i − p 1 ( x ^ i ; β ) ) ∂ 2 l ( β ) ∂ β ∂ β T = ∑ i = 1 m x ^ i x ^ i T p 1 ( x ^ i ; β ) ( 1 − p 1 ( x ^ i ; β ) ) \begin{aligned} \frac{\partial l(\beta)}{\partial \beta}&=-\sum_{i=1}^m{\hat{x}_i(y_i-p_1(\hat{x}_i;\beta))}\\ \frac{\partial^2l(\beta)}{\partial\beta\partial\beta^T}&=\sum_{i=1}^m{\hat{x}_i\hat{x}_i^Tp_1(\hat{x}_i;\beta)(1-p_1(\hat{x}_i;\beta))} \end{aligned} βl(β)ββT2l(β)=i=1mx^i(yip1(x^i;β))=i=1mx^ix^iTp1(x^i;β)(1p1(x^i;β))

【小试牛刀】

编程实现对率回归,并给出西瓜数据集3.0a上的结果。

import numpy as np
import pandas as pd
import xlrd#第一步导入数据
DataSet=pd.read_excel("西瓜数据集3.0a.xlsx")
Data=DataSet.values
#print(Data.shape) #17行4列
X=np.delete(Data,0,1)#在Data的copy基础上删除第一列编号
X=np.delete(X,2,1)
#print(X)
y=Data[:,3]
#print(y)#仍然是ndarray#利用牛顿法求解
def calp1(x,Beta):"""求解样本x在参数beta下取正例的概率p1此处Beta为列向量(3,1),x为列向量(3,1)"""temp=np.exp(np.dot(x.T,Beta))p1=temp/float(1+temp)return p1def calpartial1(X_hat,y,beta):"""求解l(beta)关于参数beta的一阶导数X_hat[i]是行向量,每一行代表一个样本"""m=len(y)partial1=0for i in range(m):x_hat=X_hat[i].reshape(3,1)#把样本x变为列矩阵temp=np.dot(x_hat,y[i]-calp1(x_hat,beta))partial1=partial1+tempreturn -partial1def calpartial2(X_hat,y,beta):"""求解l(beta)关于beta的二阶导数beta为列向量"""m=len(y)partial2=0for i in range(m):x_hat=X_hat[i].reshape(3,1)#把样本x变为列矩阵xxT=np.dot(x_hat,x_hat.T)p1=calp1(x_hat,beta)temp=p1*(1-p1)*xxTpartial2+=tempreturn partial2def LR(X,y,beta,error):"""error为误差"""#在数据集X(每行为一个样本)添加一列1#方法一X_hat=np.insert(X,2,values=1,axis=1)"""col=np.ones((17,1))#创建一个17行1列的元素全为1的二维数组Z=np.c_[X,col]print(Z)"""t=0#迭代次数while t<10000:beta1=beta-np.linalg.inv(calpartial2(X_hat,y,beta)).dot(calpartial1(X_hat,y,beta))if np.linalg.norm(beta-beta1,2)<error:return beta1else:t=t+1beta=beta1print("超过最大迭代次数,认为不收敛!")
np.random.seed(1)
beta=np.random.rand(3,1)
Beta=LR(X,y,beta,1e-5)
print(Beta) 

输出:
在这里插入图片描述

【编程中注意的一些问题】

  1. DataSet是Pandas内的对象,决策树的构建需要用到scikit-learn。
    Pandas和Scikit-learn没有完美整合,而Numpy和scikit-learn能够很好的协同使用。
    从而现将Pandas中的值转化为Numpy,然后再配合scikit-learn工作
    numpy中的ndarray为多维数组,是numpy中最为重要也是python进行科学计算非常重要和基本的数据类型。
  2. numpy矩阵运算大全见这篇博客
    numpy中文官网:https://www.numpy.org.cn/reference/
    numpy英文官网:https://numpy.org/doc/stable/index.html/

    特别注意矩阵乘法:ndarray 是 NumPy 的基础元素,NumPy 又主要是用来进行矩阵运算的.首先,在矩阵用 ±*/ 这些常规操作符操作的时候,是对元素进行操作。这和其他诸如 MATLAB 等语言不一样。 ∗ * 并没有进行矩阵乘法,而是矩阵和矩阵的元素进行了相乘。想要进行矩阵乘法计算,需要用dot方法
  3. numpy.dot()用法:
  • numpy.dot()如果处理的是一维数组,则代表向量点积,并且结果与两个参数的位置顺序无关
a1=np.array([1,2,3])
b1=np.array([2,2,2])
print(a1.shape,b1.shape)#(3,) (3,)
print(np.dot(a1,b1),np.dot(b1,a1))#12 12
  • numpy.dot()如果处理的是二维数组(矩阵),则代表矩阵乘法
a2=np.arange(3,6,1).reshape(1,3)
print(a2,a2.shape)#[[3,4,5]] (1,3)
b2=np.array([[2,4,6]])
print(b2.shape)#(1,3)
#print(np.dot(b2,a2))#报错
c2=b2.reshape(3,1)
print(c2,c2.shape)
"""
[[2][4][6]] (3,1)
"""
print(np.dot(c2,a2),np.dot(a2,c2))
"""
[[ 6  8 10][12 16 20][18 24 30]] [[52]]
"""
  1. 标量p与二维数组A相乘时,直接使用p*A
  2. 向量与二维数组做运算时,不能直接使用numpy.dot()
#解决(3,1)和(3,)在做矩阵积的时候维度不匹配的问题
np.random.seed(1)
a=np.random.randint(1,10,size=(3,1))
print(a.shape)
b=np.append(X[5],[1],0)
print(b)
c=b.reshape(1,3)
print(c)
print(np.dot(a,c))

线性判别分析

线性判别的思想非常朴素:给定训练样例集,设法将样例投影到一条直线上,使得同类样例的投影点尽可能接近,异样样例的投影点尽可能远离;在对新样本进行分类时,将其投影到同样的直线上,再根据投影点的位置来确定新样本的类别。
在这里插入图片描述
理论推导过程:

数据集: D = { ( x i , y i ) } i = 1 m , y i ∈ { 0 , 1 } , x i ∈ R d D=\{(x_i,y_i)\}_{i=1}^m,y_i\in\{0,1\},x_i\in R^d D={(xi,yi)}i=1m,yi{0,1},xiRd

X 0 = { x i ∣ y i = 0 } , X 1 = { x i ∣ y i = 1 } X_0=\{x_i|y_i=0\},X_1=\{x_i|y_i=1\} X0={xiyi=0},X1={xiyi=1}

X i ( i = 0 , 1 ) X_i(i=0,1) Xi(i=0,1)中的样例数量为 n i , n 0 + n 1 = m n_i,n_0+n_1=m ni,n0+n1=m,均值向量为 μ i = ∑ x ∈ X i x \mu_i=\sum_{x\in X_i}x μi=xXix,协方差矩阵 Σ i = 1 n i ∑ x j ∈ X i ( x j − μ i ) ( x j − μ i ) T \Sigma_i=\frac{1}{n_i}\sum_{x_j\in X_i}{(x_j-\mu_i)(x_j-\mu_i)^T} Σi=ni1xjXi(xjμi)(xjμi)T
在这里插入图片描述

向量x在向量w上的投影 a ( a ∈ R ) a(a\in R) a(aR) a = ∣ x ∣ c o s α = ∣ ω ∣ ∣ x ∣ c o s α ∣ o m e g a ∣ = ω T x ∣ ω ∣ a=|x|cos\alpha=\frac{|\omega||x|cos\alpha}{|omega|}=\frac{\omega^Tx}{|\omega|} a=xcosα=omegaω∣∣xcosα=ωωTx
则对应的投影向量为 a ω ∣ ω ∣ = ω T x ∣ ω ∣ ω ∣ ω ∣ = ω T x ω ω T ω a\frac{\omega}{|\omega|}=\frac{\omega^Tx}{|\omega|}\frac{\omega}{|\omega|}=\frac{\omega^Tx\omega}{\omega^T\omega} aωω=ωωTxωω=ωTωωTxω
容易证明, X i X_i Xi中样例在 ω \omega ω上投影的均值= X i X_i Xi中样例的均值向量在 ω \omega ω上的投影,即 1 n i ∑ x j ∈ X i ω T x j = ω T ( 1 n i ∑ x j ∈ X i x j ) = ω T μ i \frac{1}{n_i}\sum_{x_j\in X_i}\omega^Tx_j=\omega^T(\frac{1}{n_i}\sum_{x_j\in X_i}x_j)=\omega^T\mu_i ni1xjXiωTxj=ωT(ni1xjXixj)=ωTμi
从而将两类样本投影到向量 ω \omega ω上,则两类样本投影点的中心分别为 ω T μ 0 ( μ 0 T ω ) \omega^T\mu_0(\mu_0^T\omega) ωTμ0(μ0Tω) ω T μ 1 ( μ 1 T ω ) \omega^T\mu_1(\mu_1^T\omega) ωTμ1(μ1Tω)
两类样本点投影的协方差分别为 X 0 : 1 n 0 ∑ x j ∈ X 0 ( ω T x j − ω T μ 0 ) ( ω T x j − ω T μ 0 ) T 【协方差的计算公式之一】 = 1 n 0 ∑ x j ∈ X 0 ω T ( x i − μ 0 ) ( x i − μ 0 ) T ω = ω T ( 1 n 0 ∑ x j ∈ X 0 ( x i − μ 0 ) ( x i − μ 0 ) T ) ω = ω T Σ 0 ω X 1 : ω T Σ 1 ω 【同理】 \begin{aligned} X_0&:\frac{1}{n_0}\sum_{x_j\in X_0}{(\omega^Tx_j-\omega^T\mu_0)(\omega^Tx_j-\omega^T\mu_0)^T}【协方差的计算公式之一】\\ &=\frac{1}{n_0}\sum_{x_j\in X_0}{\omega^T(x_i-\mu_0)(x_i-\mu_0)^T\omega}\\ &=\omega^T\left(\frac{1}{n_0}\sum_{x_j\in X_0}{(x_i-\mu_0)(x_i-\mu_0)^T}\right)\omega\\ &=\omega^T\Sigma_0\omega\\ X_1&:\omega^T\Sigma_1\omega【同理】 \end{aligned} X0X1:n01xjX0(ωTxjωTμ0)(ωTxjωTμ0)T【协方差的计算公式之一】=n01xjX0ωT(xiμ0)(xiμ0)Tω=ωT n01xjX0(xiμ0)(xiμ0)T ω=ωTΣ0ω:ωTΣ1ω【同理】

欲使同类样本点的投影点尽可能接近,可以让同类样例投影点的协方差尽可能小,即 ω T Σ 0 ω + ω T Σ 1 ω \omega^T\Sigma_0\omega+\omega^T\Sigma_1\omega ωTΣ0ω+ωTΣ1ω尽可能小;欲使异类样本的投影点尽可能远离,可以让异类样本点投影后的中心之间的距离尽可能的大,即 ∣ ∣ ω T μ 0 − ω T μ 1 ∣ ∣ 2 2 {||\omega^T\mu_0-\omega^T\mu_1||}_2^2 ∣∣ωTμ0ωTμ1∣∣22尽可能大。 同时考虑二者,可以得到优化目标: J ( ω ) = ∣ ∣ ω T μ 0 − ω T μ 1 ∣ ∣ 2 2 ω T Σ 0 ω + ω T Σ 1 ω = ω T ( μ 0 − μ 1 ) ( μ 0 − μ 1 ) T ω ω T ( Σ 0 + Σ 1 ) ω \begin{aligned} J(\omega)&=\frac{{||\omega^T\mu_0-\omega^T\mu_1||}_2^2}{\omega^T\Sigma_0\omega+\omega^T\Sigma_1\omega}\\ &=\frac{\omega^T(\mu_0-\mu_1)(\mu_0-\mu_1)^T\omega}{\omega^T(\Sigma_0+\Sigma_1)\omega} \end{aligned} J(ω)=ωTΣ0ω+ωTΣ1ω∣∣ωTμ0ωTμ1∣∣22=ωT(Σ0+Σ1)ωωT(μ0μ1)(μ0μ1)Tω
定义类内散度矩阵 S ω S_{\omega} Sω(与 ω \omega ω无关)
S ω = Σ 0 + Σ 1 S_{\omega}=\Sigma_0+\Sigma_1 Sω=Σ0+Σ1
类间散度矩阵 S b S_b Sb(与 ω \omega ω无关)
S b = ( μ 0 − μ 1 ) ( μ 0 − μ 1 ) T S_b=(\mu_0-\mu_1)(\mu_0-\mu_1)^T Sb=(μ0μ1)(μ0μ1)T
此时优化目标可重写为 J ( ω ) = ω T S b ω ω T S ω ω J(\omega)=\frac{\omega^TS_b\omega}{\omega^TS_{\omega}\omega} J(ω)=ωTSωωωTSbω,即 S b S_b Sb S ω S_{\omega} Sω的“广义瑞利商”。

ω \omega ω的确定:
分子分母都是关于 ω \omega ω的二次项,因此J与 ω \omega ω的长度无关 J ( ω ) = ( ω ∣ ω ∣ ) T S b ( ω ∣ ω ∣ ) ( ω ∣ ω ∣ ) T S ω ( ω ∣ ω ∣ ) J(\omega)=\frac{\left(\frac{\omega}{|\omega|}\right)^TS_b\left(\frac{\omega}{|\omega|}\right)}{\left(\frac{\omega}{|\omega|}\right)^TS_{\omega}\left(\frac{\omega}{|\omega|}\right)} J(ω)=(ωω)TSω(ωω)(ωω)TSb(ωω),只与 ω \omega ω的方向有关。不是一般性,令 ω T S ω ω = 1 \omega^TS_{\omega}\omega=1 ωTSωω=1,则LDA的优化目标等价于 m i n ω − ω T S b ω s . t . ω T S ω ω = 1 \begin{aligned} min_{\omega}\quad -\omega^TS_b\omega\\ s.t.\quad \omega^TS_{\omega}\omega=1 \end{aligned} minωωTSbωs.t.ωTSωω=1

相关文章:

西瓜书第三章

广义线性模型 考虑单点可微函数 g ( ⋅ ) g(\cdot) g(⋅)&#xff0c;令 y g − 1 ( ω T x b ) yg^{-1}(\omega^{T}xb) yg−1(ωTxb)&#xff0c;这样得到的模型称为“广义线性模型”&#xff0c;其中函数 g ( ⋅ ) g(\cdot) g(⋅)称为“联系函数”。显然&#xff0c;对数线…...

关于python如何使用sqlalchemy连接sap_hana数据库

1.先安装sqlalchemy pip install sqlalchemy 2.from sqlalchemy import create_engine 3.创建数据库连接方式&#xff1a; 假设数据连接方式如下&#xff1a; usernameH_TEOPT passwordww122222 jdbcUrljdbc:sap://192.163.1.161:21681/?currentschema 那么使用sqlalchemy 的…...

微信小程序教学系列(5)

微信小程序教学系列 第五章&#xff1a;小程序发布与推广 第一节&#xff1a;小程序发布流程介绍 小伙伴们&#xff0c;欢迎来到第五章的教学啦&#xff01;在这一章中&#xff0c;我们将一起来探索小程序的发布与推广流程。你准备好了吗&#xff1f;让我们开始吧&#xff0…...

【计算机网络篇】TCP协议

✅作者简介&#xff1a;大家好&#xff0c;我是小杨 &#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; TCP协议 1&#xff0c;TCP 简介 TCP&#xff08;Transmission Control Protocol&#xff09;是…...

Disruptor并发编程框架

Disruptor是一款高性能的并发编程框架,主要具有以下特点和功能: 1. RingBuffer环形数据结构 Disruptor的核心数据结构是RingBuffer环形队列,用于存储客户端的并发数据并在生产者和消费者之间传递。队列以批量方式的顺序存储,可以高效地进行并发读写操作。 2. 无锁设计 Disrup…...

matlab 点云精配准(1)——point to point ICP(点到点的ICP)

目录 一、算法原理参考文献二、代码实现三、结果展示四、参考链接本文由CSDN点云侠原创,爬虫自重。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫。 一、算法原理 参考文献 [1] BESL P J,MCKAY N D.A method for registration of 3-Dshapes[J].IEEE Tran…...

【JVM】运行时数据区域

文章目录 说明程序计数器虚拟机栈本地方法栈Java堆方法区运行时常量池直接内存 说明 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途&#xff0c;以及创建和销毁的时间&#xff0c;有的区域随着虚拟机进程的启动而一直…...

uniapp踩坑合集

1、onPullDownRefresh下拉刷新不生效 pages.json对应的style中enablePullDownRefresh设置为true&#xff0c;开启下拉刷新 {"path" : "pages/list/list","style" :{"navigationBarTitleText": "页面标题名称","enable…...

再JAVA中如何使用qsort对类进行排序?

目录 结论&#xff1a; 解析&#xff1a; 结论&#xff1a; import java.util.Arrays;class Person implements Comparable<Person>{public String name;public int age;public Person(String name, int age) {this.name name;this.age age;}Overridepublic Stri…...

docker安装clickhouse

安装 docker安装 创建clickhouse目录 mkdir -P /data/clickhouse/datamkdir -P /data/clickhouse/confmkdir -P /data/clickhouse/log 拉取镜像 这里直接拉取最新镜像, 如果需要某个特定版本, 则再拉取的时候指定版本号即可. docker pull clickhouse/clickhouse-server 启动临…...

解决`idea`中`database`工具查询起别名乱码问题

文章目录 解决idea中database工具查询起别名乱码问题场景复现如何解决方式一 设置编码方式二&#xff1a;修改字体 原因说明 解决idea中database工具查询起别名乱码问题 场景复现 使用Idea做查询的并且起别名出现了中文乱码 如何解决 方式一 设置编码 settings->输入框输…...

UE4/5Niagara粒子特效之Niagara_Particles官方案例:1.5->2.3

目录 之前的文章&#xff1a; 1.5 Blend Attributes by Value 发射器更新 粒子生成 粒子更新 2.1 Static Beams ​编辑 发射器更新&#xff1a; 粒子生成 粒子更新 2.2 Dynamic Beams 没有开始模拟前的效果是&#xff1a; 开始模拟后的效果是&#xff1a; 发射器更新 …...

Docker 容器数据卷

Docker挂载主机目录访问如果出现cannot open directory .: Permission denied 解决办法&#xff1a;在挂载目录后多加一个--privilegedtrue参数即可 如果是CentOS7安全模块会比之前系统版本加强&#xff0c;不安全的会先禁止&#xff0c;所以目录挂载的情况被默认为不安全的行…...

STM32--MPU6050与I2C外设

文章目录 前言MPU6050参数电路MPU6050框图 IIC外设框图 IIC的基本结构软件IIC实现MPU6050硬件IIC实现MPU6050 前言 在51单片机专栏中&#xff0c;用过I2C通信来进行实现AT24C02的数据存储&#xff1b; 里面介绍的是利用程序的编程来实现I2C的时序&#xff0c;进而实现AT24C02与…...

项目管理实战笔记1:项目管理常识

序 看了下极客时间的《项目管理实战》&#xff0c;觉得跟之前学习PMP的标准资料还是有所侧重。重新整理下&#xff0c;相比书上繁杂的知识&#xff0c;这个更通俗易懂。 1 角色转换&#xff1a;三大误区 误区1&#xff1a;事必躬亲 自己做事情是可控的&#xff0c;做项目依赖…...

时序分解 | MATLAB实现基于SVMD逐次变分模态分解的信号分解分量可视化

时序分解 | MATLAB实现基于SVMD逐次变分模态分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于SVMD逐次变分模态分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 SVMD分解算法&#xff0c;分解结果可视化&#xff0c;MATLAB程序&#xff…...

阿里云访问端口被限制解决方法记录

阿里云服务器&#xff0c;80端口可以访问&#xff0c;但是加入了安全组端口8080 通过公网访问改端口策略&#xff0c;发现不能被访问 问题出在防火墙&#xff0c;需要重置一下 解决方法&#xff1a; 在运行的服务器上执行如下命令&#xff1a; # iptables -A INPUT -j ACCEP…...

antd5源码调试环境启动(MacOS)

将源码下载至本地 这里antd5 版本是5.8.3 $ git clone gitgithub.com:ant-design/ant-design.git $ cd ant-design $ npm install $ npm start前提&#xff1a;安装python3、node版本18.14.0(这是本人当前下载的版本&#xff09; python3安装教程可参考&#xff1a;https://…...

单片机使用基于时间片轮询系统的-状态机-[1]

目的&#xff1a;【1】用C实现一个超轻量化任务管理系统 【2】具有任务suspend, resume, runonce ,auto loop ,task_delay功能 【3】易于移植&#xff0c;不涉及硬件底层。 示例例码&#xff1a; 利用switch case结构实现了单一层的 task_delay功能。弊端就是switch..case不…...

前端开发怎么解决性能优化的问题? - 易智编译EaseEditing

前端性能优化是确保网站或应用在加载速度、响应性和用户体验等方面达到最佳状态的关键任务。以下是一些解决前端性能优化问题的方法&#xff1a; 压缩和合并代码&#xff1a; 压缩和合并CSS、JavaScript和HTML文件可以减少文件大小&#xff0c;加快加载速度。使用压缩工具&am…...

共享球拍小程序:打破拥有束缚,尽享运动乐趣

市场前景&#xff1a; 随着健身和运动的流行趋势&#xff0c;越来越多的人加入了各种体育项目。然而&#xff0c;拥有球拍作为体育装备的成本较高&#xff0c;对于想要尝试不同运动的人来说&#xff0c;这可能是个阻碍。共享球拍小程序迎合了这一需求&#xff0c;提供了一个经济…...

uniapp 微信小程序 绘制海报,长按图片分享,保存海报

uView UI 2.0 dcloud 插件市场地址 弹窗海报源码 <template><!-- 推荐商品弹窗 --><u-popup :show"haibaoShow" mode"center" round26rpx z-index10076 bgColortransparent safeAreaInsetTop close"goodsclose"><image …...

爬虫异常捕获与处理方法详解

Hey&#xff01;作为一名专业的爬虫代理供应商&#xff0c;我今天要和大家分享一些关于爬虫异常捕获与处理的方法。在进行爬虫操作时&#xff0c;我们经常会遇到各种异常情况&#xff0c;例如网络连接错误、请求超时、数据解析错误等等。这些异常情况可能会导致程序崩溃或数据丢…...

制作网络课堂学习平台(标签嵌套,后代选择器)

网络课堂学习平台 课程 1 这是课程 1 的描述。 模块 1 这是模块 1 的描述。 查看详情 模块 2 这是模块 2 的描述。 查看详情 课程 2 这是课程 2 的描述。 模块 1 这是块 2 的描述。 查看详情...

基于医疗领域数据微调LLaMA——ChatDoctor模型

文章目录 ChatDoctor简介微调实战下载仓库并进入目录创建conda环境并配置环境&#xff08;安装相关依赖&#xff09;下载模型文件微调数据微调过程全量微调基于LoRA的微调基于微调后的模型推理 ChatDoctor简介 CHatDoctor论文&#xff1a; ChatDoctor: A Medical Chat Model F…...

UDP TCP 报文内容

1.UDP 2.TCP 源/目的端口号:表示数据是从哪个进程来,到哪个进程去; 32位序号/32位确认号:后面详细讲;4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是15*460 6位标志位: o URG:紧急指针是否有效 ——urgent 紧急的 o ACK:确认号是否有…...

Boost开发指南-4.8operators

operators C提供了强大且自由的操作符重载能力&#xff0c;可以把大多数操作符重新定义为函数&#xff0c;使操作更加简单直观。这方面很好的例子就是标准库中的string和 complex&#xff0c;可以像操作内置类型int、double那样对它们进行算术运算和比较运算&#xff0c;非常方…...

c# 泛型约束

在C#中&#xff0c;泛型约束用于指定泛型类型参数的限制条件&#xff0c;以确保类型参数满足特定的条件。以下是C#中常见的泛型约束&#xff1a; where T : struct&#xff1a; 这个约束要求类型参数必须是一个值类型&#xff08;如int、float等&#xff09;。 where T : cla…...

android frida

Frida 是一个用于动态分析、调试和修改 Android 应用程序的强大工具。它的主要作用包括&#xff1a; 代码注入和Hooking&#xff1a; Frida 允许您在运行时修改和监视应用程序的行为。您可以通过Frida注入JavaScript代码到目标应用程序中&#xff0c;然后使用该代码来Hook&…...

Linux下的Shell编程——正则表达式入门(四)

前言&#xff1a; 正则表达式使用单个字符串来描述、匹配一系列符合某个语法规则的字符串。在很多文本编辑器里&#xff0c;正则表达式通常被用来检索、替换那些符合某个模式的文本。 在Linux 中&#xff0c;grep&#xff0c;sed&#xff0c;awk 等文本处理工具都支持…...

使用VisualStudio制作上位机(一)

文章目录 使用VisualStudio制作上位机(一)写在前面第一部分:创建应用程序第二部分:GUI主界面设计使用VisualStudio制作上位机(一) Author:YAL 写在前面 1.达到什么目的呢 本文主要讲怎么通过Visual Studio 制作上位机,全文会以制作过程来介绍怎么做,不会去讲解具体…...

【前端从0开始】JavaSript——自定义函数

函数 函数是一个可重用的代码块&#xff0c;用来完成某个特定功能。每当需要反复执行一段代码时&#xff0c;可以利用函数来避免重复书写相同代码。函数包含着的代码只能在函数被调用时才会执行&#xff0c;就可以避免页面载入时执行该脚本在JavaScript中&#xff0c;可以使用…...

如何在Windows、Mac和Linux操作系统上安装Protocol Buffers(protobuf)编译器

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…...

简单介绍 CPU 的工作原理

内部架构 CPU 的根本任务就是执行指令&#xff0c;对计算机来说最终都是一串由 0 和 1 组成的序列。CPU 从逻辑上可以划分成 3 个模块&#xff0c;分别是控制单元、运算单元和存储单元 。其内部架构如下&#xff1a; 【1】控制单元 控制单元是整个CPU的指挥控制中心&#xff…...

UE4/5数字人MetaHuman的控制绑定资产使用

目录 开始操作 找到控制绑定资产 放入控制绑定资产 ​编辑 生成动画资产 开始操作 首先我们创建一个关卡序列&#xff1a; 打开后将我们的数字人放进去【右键&#xff0c;第一个添加进去】&#xff1a; 我们会自动进入动画模式&#xff0c;没有的话&#xff0c;就自己…...

二、11.系统交互

fork 函数原型是 pid_t fork(void&#xff09;&#xff0c;返回值是数字&#xff0c;该数字有可能是子进程的 pid &#xff0c;有可能是 0&#xff0c;也有可能是-1 。 1个函数有 3 种返回值&#xff0c;这是为什么呢&#xff1f;可能的原因是 Linux 中没有获取子进程 pid 的方…...

敏捷管理工具/国内软件敏捷开发工具

​Scrum中非常强调公开、透明、直接有效的沟通&#xff0c;这也是“可视化的管理工具”在敏捷开发中如此重要的原因之一。通过“可视化的管理工具”让所有人直观的看到需求&#xff0c;故事&#xff0c;任务之间的流转状态&#xff0c;可以使团队成员更加快速适应敏捷开发流程。…...

Selenium环境+元素定位大法

selenium 与 webdriver Selenium 是一个用于 Web 测试的工具&#xff0c;测试运行在浏览器中&#xff0c;就像真正的用户在手工操作一样。支持所有主流浏览器 WebDriver 就是对浏览器提供的原生API进行封装&#xff0c;使其成为一套更加面向对象的Selenium WebDriver API。 使…...

Vue3 用父子组件通信实现页面页签功能

一、大概流程 二、用到的Vue3知识 1、组件通信 &#xff08;1&#xff09;父给子 在vue3中父组件给子组件传值用到绑定和props 因为页签的数组要放在父页面中&#xff0c; data(){return {tabs: []}}, 所以顶部栏需要向父页面获取页签数组 先在页签页面中定义props用来接…...

HCIP STP协议

STP协议 STP协议概念生成树为什么要用STP STP名词解释根网桥根端口指定端口非指定端口 STP的版本802.1DPVSTPVST 快速生成树 STP协议概念 IEEE 802.1d STP&#xff08;生成树协议&#xff0c;Spanning-Tree Protocol&#xff09;协议&#xff1a; ①使冗余端口置于“阻塞状态”…...

链表的顶级理解

目录 1.链表的概念及结构 2.链表的分类 单向或者双向 带头或者不带头 循环或者非循环 3.无头单向非循环链表的实现 3.1创建单链表 3.2遍历链表 3.3得到单链表的长度 3.4查找是否包含关键字 3.5头插法 3.6尾插法 3.7任意位置插入 3.8删除第一次出现关键字为key的节点 …...

探索贪心算法:理解与实现JAVA语言

探索贪心算法&#xff1a;理解与实现 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种基于每一步的最优选择来达到整体最优的算法思想。尽管贪心算法并不适用于所有问题&#xff0c;但它在很多情况下都能够提供高效、近似的解决方案。本文将深入探讨贪心算法的基本概…...

数字孪生技术对旅游行业能起到什么作用?

随着疫情对我们生活影响的淡化&#xff0c;旅游行业迎来了新的春天&#xff0c;暑期更是旅游行业的小高潮&#xff0c;那么作为一个钻研数字孪生行业的小白&#xff0c;本文就着旅游的话题以及对旅游的渴望带大家一起探讨一下数字孪生对智慧旅游发展的作用~ 数字孪生作为一种虚…...

攻防世界-Web_php_include

原题 解题思路 php://被替换了&#xff0c;但是只做了一次比对&#xff0c;改大小写就可以绕过。 用burp抓包&#xff0c;看看有哪些文件 flag明显在第一个PHP文件里&#xff0c;直接看...

Python Opencv实践 - 直方图显示

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_COLOR) print(img.shape)#图像直方图计算 #cv.calcHist(images, channels, mask, histSize, ranges, hist, accumulate) #images&…...

2分钟搭建自己的GPT网站

如果觉得官方免费的gpt&#xff08;3.5&#xff09;体验比较差&#xff0c;总是断开&#xff0c;或者不会fanqiang&#xff0c;那你可以自己搭建一个。但前提是你得有gpt apikey。年初注册的还有18美金的额度&#xff0c;4.1号后注册的就没有额度了。不过也可以自己充值。 有了…...

deepdiff比较两个json文件数据差异性

deepdiff比较两个json文件数据差异性 Python代码片&#xff1a; import json import sysfrom deepdiff import DeepDiff from deepdiff import grep, DeepSearch from deepdiff import DeepHash# print(DeepDiff("abc", "abcd", ignore_orderTrue))class …...

文件内容搜索工具 - Python实现

在本篇文章中&#xff0c;我们将介绍如何使用 wxPython 库创建一个简单的文件搜索工具。这个工具允许用户选择一个文件夹&#xff0c;并在该文件夹中的所有 .py 文件中查找指定的文字&#xff0c;并显示匹配的位置。 C:\pythoncode\blog\searchwordinpyfile.py 代码实现 我们首…...

vue静态html加载外部组件

当我们在开发vue应用时, 使用的是html页面开发, 需要引用外部vue组件, 怎么办呢, 首先我们引用http-vue-loader.js文件, 像下面这样: <script src"/assets/javascript/vue.min.js"></script> <script src"/assets/javascript/http-vue-loader.j…...

WebSocket 中的心跳是什么,有什么作用?

在网络应用开发中&#xff0c;WebSocket 是一种重要的通信协议&#xff0c;它允许客户端和服务器之间建立持久性的双向通信连接。然而&#xff0c;为了保持连接的稳定性&#xff0c;WebSocket 中的心跳是一个不可或缺的概念。本文将详细介绍 WebSocket 中的心跳是什么&#xff…...