矩阵快速幂

1.快速幂

快速幂也叫二进制取幂,想要快速求出 a n a^n an的结果就用它来求。

a n a^n an表示将n个a乘在一起,时间复杂度是O(n) 级别,如果n太大的话这种方法就不适用了。

如果使用快速幂,时间复杂度能达到O( l o g 2 log_2 log2n),因为n有⌊ l o g 2 log_2 log2n⌋ + 1 个二进制位,所以当知道了每一位的值后,只需要通过 l o g 2 log_2 log2n次乘法就可计算出 a n a^n an

用快速幂进行计算
例如计算 a 9 a^9 a9,9的二进制是1001, 9 = 1 × 2 0 2^0 20 + 0 × 2 1 2^1 21 + 0 × 2 2 2^2 22 +1 × 2 3 2^3 23 = 2 1 2^1 21 + 2 3 2^3 23 ;
因此 a 9 a^9 a9 = a(2^1 + 2^3)= a2^1 * a2^3 , 也就是a1 * a8。现在这样就快多了吧,原来9个a连乘要计算8次乘法,现在使用快速幂只要乘两次。
但是像a8这种式子好像不是很好求的样子。。。

long long pow(int a, int b)
{
    long long int ans = 1;
    while(b)
    {
        if(b & 1) //判断b的二进制最后一位是不是1
        {
        	 ans *= a;
        }
        a *= a;  //累乘,以便对ans做出贡献
        b >>= 1; //b右移一位,去掉最后一位
    }
    return ans;
}

关于代码中累乘 a *= a
a *= a 即 a = a2,再下一步就是a2 * a2 = a4,再下一步就是a4 * a4 = a8… …
这样随着b右移,a也发生变化:a1 -> a2->a4->a8… … a的指数恰好是2x形式,再看a9 = a1 * a8,类似于 a8这样的式子就完美求出来了,当b二进制当前的末位为1的时候,只要把a乘给ans就能更新ans了。

2.矩阵快速幂

两个矩阵相乘
( a 11 a 12 . . . a 1 n a 21 a 22 . . . a 2 n a 31 a 32 . . . a 3 n ) ∗ ( b 11 b 12 . . . b 1 n b 21 b 22 . . . b 2 n b 31 b 32 . . . b 3 n ) = ( c 11 c 12 . . . c 1 n c 21 c 22 . . . c 2 n c 31 c 32 . . . c 3 n ) \begin{pmatrix} a_{11} & a_{12}& ... & a_{1n} \\ a_{21} & a_{22} & ... & a_{2n} \\ a_{31} & a_{32} & ... & a_{3n} \end{pmatrix} *\begin{pmatrix} b_{11} & b_{12} & ... & b_{1n} \\ b_{21} & b_{22} & ... & b_{2n} \\ b_{31} & b_{32} & ... & b_{3n} \end{pmatrix}=\begin{pmatrix} c_{11} & c_{12}& ... & c_{1n} \\ c_{21} & c_{22} & ... & c_{2n} \\ c_{31} & c_{32} & ... & c_{3n} \end{pmatrix} a11a21a31a12a22a32.........a1na2na3nb11b21b31b12b22b32.........b1nb2nb3n=c11c21c31c12c22c32.........c1nc2nc3n
举个例子
( a b c d ) ∗ ( a 1 b 1 c 1 d 1 ) = ( a ∗ a 1 + b ∗ c 1 a ∗ b 1 + b ∗ d 1 c ∗ a 1 + d ∗ c 1 c ∗ b 1 + d ∗ d 1 ) \begin{pmatrix} a & b \\ c & d \end{pmatrix} * \begin{pmatrix} a_1 & b_1 \\ c_1 & d_1 \end{pmatrix}=\begin{pmatrix} a*a_1 +b*c_1 & a*b_1+b*d_1 \\ c*a_1+d*c_1 & c*b_1+d*d_1 \end{pmatrix} (acbd)(a1c1b1d1)=(aa1+bc1ca1+dc1ab1+bd1cb1+dd1)

注意:
1.矩阵A*B必须满足 A的列数=B的行数

2.若矩阵A是一个m行s列的矩阵,矩阵B是一个s行n列的矩阵,则C=A*B是一个m行n列的矩阵

矩阵快速幂
设A为矩阵,求An,若直接相乘,需要连乘n-1次,时间复杂度为O(n),
使用矩阵快速幂,时间复杂度为O( l o g 2 n ) log_2n) log2n)

那么如何实现矩阵快速幂呢?只要快速幂中的乘法改成矩阵的乘法就行了。

const int N = 2;
int ans[N][N];
int temp[N][N];
int num[N][N];
void multi(int a[][N], int b[][N]) //两个矩阵相乘
{
    memset(temp, 0, sizeof(temp));
    for(int i = 0; i < N; i++)
        for(int j = 0; j < N; j++)
        for(int k = 0; k < N; k++)
        temp[i][j] = temp[i][j] + a[i][k] * b[k][j];

    for(int i = 0; i < N; i++)
        for(int j = 0; j < N; j++)
        a[i][j] = temp[i][j];
}
void MatPow(int a[][N], int n)  //计算矩阵a的n次方
{
    memset(res, 0, sizeof(res));
    for(int i = 0; i < N; i++) ans[i][i] = 1; //初始化为单位矩阵,相当于快速幂中的ans = 1

    while(n)
    {
        if(n&1)
        {
            multi(ans, a); //矩阵ans与矩阵a相乘
        }
        multi(a, a);//矩阵a自乘
        n >>= 1;
    }
}

矩阵快速幂主要是用来求一个复杂递推式的某一项问题,只要构造出了关系矩阵,问题就好解决了。

如何构造矩阵

首先说明一下,能用矩阵快速幂优化的递推类型是f[n]=2f[n-1]+3f[n-2]+n3+1这类的,也就是递推要是线性的,且f[n-i]的系数要是常数,可以含有n的多项式。

下面介绍一些递推式:
递推式1.斐波那契数列 F n = F n − 1 + F n − 2 , F 0 = 1 , F 1 = 2 , 求 F n F_n=F_{n-1}+F_{n-2},F_0=1, F_1=2,求F_n Fn=Fn1+Fn2,F0=1,F1=2,Fn
设转换矩阵为A,那么
A ∗ ( F n − 2 F n − 1 ) = ( F n − 1 F n ) = ( F n − 1 F n − 1 + F n − 2 ) A* \begin{pmatrix} F_{n-2} \\ F_{n-1} \end{pmatrix} = \begin{pmatrix} F_{n-1} \\ F_{n} \end{pmatrix} =\begin{pmatrix} F_{n-1} \\ F_{n-1} +F_{n-2} \end{pmatrix} A(Fn2Fn1)=(Fn1Fn)=(Fn1Fn1+Fn2)

之前说过,若矩阵a是一个m行s列的矩阵,矩阵b是一个s行n列的矩阵,则c=a*b是一个m行n列的矩阵


易知,A是一个2×2的矩阵。

A = ( a b c d ) A= \begin{pmatrix} a & b \\ c & d \end{pmatrix} A=(acbd)
那么
a ∗ F n − 2 + b ∗ F n − 1 = F n − 1 a * F_{n-2}+b*F_{n-1} = F_{n-1} aFn2+bFn1=Fn1,
c ∗ F n − 2 + d ∗ F n − 1 = F n − 1 + F n − 2 c * F_{n-2}+d*F_{n-1} = F_{n-1}+F_{n-2} cFn2+dFn1=Fn1+Fn2
得a=0,b=1,c=1,d=1
A = ( 0 1 1 1 ) A= \begin{pmatrix} 0 & 1 \\ 1 & 1 \end{pmatrix} A=(0111)
这样就求出了转换矩阵A

A ∗ ( F 1 F 2 ) = ( F 2 F 3 ) A* \begin{pmatrix} F_1 \\ F_2 \end{pmatrix} = \begin{pmatrix} F_2 \\ F_3 \end{pmatrix} A(F1F2)=(F2F3)

A ∗ ( F 2 F 3 ) = ( F 3 F 4 ) A* \begin{pmatrix} F_2 \\ F_3 \end{pmatrix} = \begin{pmatrix} F_3 \\ F_4 \end{pmatrix} A(F2F3)=(F3F4)
A n − 1 ∗ ( F 1 F 2 ) = ( F n F n + 1 ) A^{n-1}* \begin{pmatrix} F_1 \\ F_2 \end{pmatrix} = \begin{pmatrix} F_n \\ F_{n+1} \end{pmatrix} An1(F1F2)=(FnFn+1)

最后得到的矩阵的第一个元素即为 F n F_n Fn
一些类似的数列:

(1) F n = F n − 1 + F n − 2 + 1 , F 1 = 1 , F 2 = 2 , 求 F n F_n = F_{n-1}+F_{n-2} + 1,F_1=1, F_2=2,求F_n Fn=Fn1+Fn2+1,F1=1,F2=2,Fn

A ∗ ( F n − 2 F n − 1 1 ) = ( F n − 1 F n 1 ) = ( F n − 1 F n − 2 + F n − 1 + 1 1 ) A* \begin{pmatrix} F_{n-2} \\ F_{n-1} \\ 1 \end{pmatrix} = \begin{pmatrix} F_{n-1} \\ F_n\\ 1 \end{pmatrix}= \begin{pmatrix} F_{n-1} \\ F_{n-2}+F_{n-1} + 1 \\ 1 \end{pmatrix} AFn2Fn11=Fn1Fn1=Fn1Fn2+Fn1+11
解得 A = ( 0 1 0 1 1 0 0 1 1 ) A= \begin{pmatrix} 0 & 1 & 0\\ 1 & 1 & 0 \\ 0 & 1 & 1 \end{pmatrix} A=010111001
F n F_n Fn:
A n − 1 ∗ ( F 1 F 2 1 ) = ( F n F n + 1 1 ) A^{n-1}* \begin{pmatrix} F_1 \\ F_2 \\ 1 \end{pmatrix} = \begin{pmatrix} F_n \\ F_{n+1} \\ 1 \end{pmatrix} An1F1F21=FnFn+11
最后得到的矩阵的第一个元素即为 F n F_n Fn

(2) F n = F n − 1 + F n − 2 + n + 1 , F 0 = 1 , F 1 = 2 , 求 F n F_n = F_{n-1}+F_{n-2} + n + 1,F_0=1, F_1=2,求F_n Fn=Fn1+Fn2+n+1,F0=1,F1=2,Fn

A ∗ ( F n − 2 F n − 1 n 1 ) = ( F n + 1 F n n + 1 1 ) = ( F n + 1 F n − 2 + F n − 1 + n + 1 n + 1 1 ) A* \begin{pmatrix} F_{n-2} \\ F_{n-1} \\ n \\ 1 \end{pmatrix} = \begin{pmatrix} F_{n+1} \\ F_n \\ n+1 \\ 1 \end{pmatrix} = \begin{pmatrix} F_{n+1} \\ F_{n-2}+F_{n-1}+n+1 \\ n+1 \\ 1 \end{pmatrix} AFn2Fn1n1=Fn+1Fnn+11=Fn+1Fn2+Fn1+n+1n+11 解得 A = ( 0 1 0 0 1 1 0 0 0 1 1 0 0 1 1 1 ) A= \begin{pmatrix} 0 & 1 & 0 & 0 \\ 1 & 1 & 0 & 0\\ 0 & 1 & 1 & 0 \\ 0 & 1 & 1 & 1 \end{pmatrix} A=0100111100110001
F n F_n Fn: A n − 1 ∗ ( F 1 F 2 3 1 ) = ( F n F n + 1 n + 1 1 ) A^{n-1}* \begin{pmatrix} F_1 \\ F_2\\ 3 \\ 1 \end{pmatrix} = \begin{pmatrix} F_n \\ F_{n+1} \\ n+1 \\ 1 \end{pmatrix} An1F1F231=FnFn+1n+11

(3) F n = F n − 2 + F n − 1 , F 1 = F 2 = 1 , 求 F n 的 前 n 项 和 S n F_n=F_{n-2}+F_{n-1},F_1=F_2=1,求F_n的前n项和S_n Fn=Fn2+Fn1,F1=F2=1,FnnSn

同理求A:
A ∗ ( F n − 2 F n − 1 S n − 2 ) = ( F n − 1 F n S n − 1 ) = ( F n − 1 F n − 2 + F n − 1 S n − 2 + F n − 1 ) A* \begin{pmatrix} F_{n-2} \\ F_{n-1} \\ S_{n-2} \end{pmatrix} = \begin{pmatrix} F_{n-1} \\ F_n\\ S_{n-1} \end{pmatrix}= \begin{pmatrix} F_{n-1} \\ F_{n-2}+F_{n-1} \\ S_{n-2}+F_{n-1} \end{pmatrix} AFn2Fn1Sn2=Fn1FnSn1=Fn1Fn2+Fn1Sn2+Fn1
解得 A = ( 0 1 0 0 0 1 1 1 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 1 1 ) A= \begin{pmatrix} 0 & 1 & 0 & 0 & 0\\ 1 & 1 & 1 & 0 & 0\\ 0 & 0 & 1 & 0 & 0\\ 0 & 1 & 0 & 1 & 0\\ 0 & 1 & 0 & 1 & 1 \end{pmatrix} A=0100011011011000001100001

观察上面数各列求出的转换矩阵A,你会发现它们有一些相似性,
一般的,如果有 F n = p ∗ F n − 2 + q ∗ F n − 1 + r ∗ n + s F_n=p*F_{n-2} + q * F_{n-1} + r * n + s Fn=pFn2+qFn1+rn+s,可构造矩阵A为:
A = ( 0 p 0 0 0 1 q 1 0 0 0 0 1 0 0 0 r 0 1 0 0 s 0 1 1 ) A= \begin{pmatrix} 0 & p & 0 & 0 & 0\\ 1 & q & 1 & 0 & 0\\ 0 & 0 & 1 & 0 & 0\\ 0 & r & 0 & 1 & 0\\ 0 & s & 0 & 1 & 1 \end{pmatrix} A=01000pq0rs011000001100001
递推式2: F n = k ∗ F n − 1 + n 2 Fn=k*F_{n-1}+n^2 Fn=kFn1+n2
按照之前的方法写:
A ∗ ( F n − 1 n 2 ) = ( F n ( n + 1 ) 2 ) = ( k ∗ F n − 1 + n 2 ( n + 1 ) 2 ) A* \begin{pmatrix} F_{n-1} \\ n^2 \end{pmatrix} = \begin{pmatrix} F_n \\ (n+1)^2 \end{pmatrix}= \begin{pmatrix} k*F_{n-1}+n^2 \\ (n+1)^2 \end{pmatrix} A(Fn1n2)=(Fn(n+1)2)=(kFn1+n2(n+1)2)易知A是2×2的矩阵,不访设 A = ( a b c d ) A= \begin{pmatrix} a & b \\ c & d \end{pmatrix} A=(acbd)
得到:
a ∗ F n − 1 + b ∗ n 2 = k ∗ F n − 1 + n 2 a*F_{n-1} + b * n^2 = k* F_{n-1} + n^2 aFn1+bn2=kFn1+n2 (式子1)
c ∗ F n − 1 + d ∗ n 2 = ( n + 1 ) 2 = n 2 + 2 n + 1 c*F_{n-1}+d*n^2=(n+1)^2=n^2+2n+1 cFn1+dn2=(n+1)2=n2+2n+1(式子2)
解到这里你会发现式子2中有一个关于n的一次项2n和一个常数项,此时求出的abcd的值是不对的,因为将abcd带入原式后计算,是得不到 ( n + 1 ) 2 (n+1)^2 (n+1)2这个式子的,所以不能这样构造。那应该怎么构造呢,在式子2中有一个一次项和一个常数项,那就再构造时把一次项和常数项加入。
A ∗ ( F n − 1 n 2 n 1 ) = ( k ∗ F n − 1 + n 2 ( n + 1 ) 2 n + 1 1 ) A* \begin{pmatrix} F_{n-1} \\ n^2 \\ n \\ 1 \end{pmatrix} = \begin{pmatrix} k* F_{n-1}+n^2 \\ (n+1)^2 \\ n+1 \\ 1 \end{pmatrix} AFn1n2n1=kFn1+n2(n+1)2n+11

A = ( k 1 0 0 0 1 2 1 0 0 1 0 0 0 0 1 ) A= \begin{pmatrix} k & 1 & 0 & 0 \\ 0 & 1 & 2 & 1\\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} A=k000110002100101
递推式3: F n = k ∗ F n − 1 + n 3 F_n=k*F_{n-1}+n^3 Fn=kFn1+n3
同理可求得:
A = ( k 1 0 0 0 0 1 3 3 1 0 0 1 2 1 0 0 0 1 1 0 0 0 0 1 ) A= \begin{pmatrix} k & 1 & 0 & 0 & 0\\ 0 & 1 & 3 & 3 & 1\\ 0 & 0 & 1 & 2 & 1 \\ 0 & 0 & 0 & 1 & 1 \\ 0 & 0 & 0 & 0 & 1 \end{pmatrix} A=k000011000031000321001111
递推式4: F n = k ∗ F n − 1 + b n F_n=k*F_{n-1}+b^n Fn=kFn1+bn
A ∗ ( F n − 1 b n ) = ( F n b n + 1 ) = ( k ∗ F n − 1 + b n b n ∗ b ) A* \begin{pmatrix} F_{n-1} \\ b^n \end{pmatrix}= \begin{pmatrix} F_n \\ b^{n+1} \end{pmatrix}= \begin{pmatrix} k*F_{n-1}+b^n \\ b^n * b \end{pmatrix} A(Fn1bn)=(Fnbn+1)=(kFn1+bnbnb)
解得:
A = ( k 1 0 b ) A= \begin{pmatrix} k & 1 \\ 0 & b \end{pmatrix} A=(k01b)

几道模板题:
1.Fibonacci
2.Tr A
3.A Simple Math Problem

<think>好的,我现在需要帮助用户理解如何通过P-R曲线图评估模型性能的优劣。用户之前的问题是关于P值的,现在转到了P-R曲线,看起来他可能在深入学习模型评估指标。 首先,我得回顾一下用户提供的引用内容。引用1提到PR曲线以召回率和精确率为轴,引用3指出在数据不平衡时PR曲线更适合,而引用4给出了ROC和PR曲线的定义。用户现在的疑问是PR曲线的判断标准,需要明确如何根据图表判断模型好坏。 接下来,我需要整理PR曲线的关键点。PR曲线Precision-Recall曲线,横轴是Recall,纵轴是Precision。当正样本少时,PR曲线比ROC更有参考价值,这点需要强调。然后,判断标准可能包括曲线整体位置、平衡点(比如F1分数)、曲线下面积(AP)以及曲线波动情况。 用户可能还关心如何实际操作,比如在Python中如何绘制PR曲线,或者如何计算AP值。不过用户的问题集中在判断标准上,所以代码示例可以作为补充,但重点应放在解释指标上。 另外,用户之前的问题涉及P值的应用注意事项,可能需要将统计假设检验中的概念与模型评估联系起来,但这里可能不需要,除非有直接关联。需要注意保持回答的专注性。 还要考虑用户可能的误区,比如认为PR曲线越陡峭越好,或者只关注单一指标而忽略整体趋势。需要指出PR曲线在不同阈值下的表现,以及如何综合判断。 最后,生成相关问题时要围绕PR曲线的应用场景、与其他指标的比较、实际应用中的调整方法等,帮助用户进一步学习。</think>### 如何通过P-R曲线图评估模型性能? P-R曲线Precision-Recall Curve)通过展示不同分类阈值下的**精确率(Precision)**与**召回率(Recall)**的权衡关系,帮助判断模型在类别不平衡场景下的性能优劣。以下是具体判断标准: --- #### **1. 曲线整体位置** - **越靠近右上角性能越好**: 当曲线整体位置偏向坐标系右上方时,表示模型在保持高召回率的同时实现了高精确率。 例如:若曲线Recall=0.8时仍能保持Precision>0.9,说明模型对正类的识别能力较强[^3]。 - **与基线对比**: 若数据中正样本占比为$p$,则基线(随机猜测模型)的PR曲线为水平线$y=p$。 **模型曲线需显著高于基线**,否则表明模型无实际预测能力。 --- #### **2. 曲线下面积(Average Precision, AP)** - **AP值量化指标**: 计算PR曲线下方的面积(AP值),AP值越接近1,模型性能越好。 数学表达式为: $$AP = \sum_{k=1}^{n} (R_k - R_{k-1}) \cdot P_k$$ 其中$R_k$为召回率,$P_k$为对应精确率[^3]。 - **实际应用**: - AP>0.9:极优性能 - AP∈[0.7,0.9]:良好性能 - AP<0.5:需优化模型 --- #### **3. 曲线波动与平衡点** - **平滑性分析**: 曲线波动小(平滑下降)表明模型在不同阈值下性能稳定;剧烈震荡则反映模型对阈值敏感,泛化能力较差。 - **F1分数平衡点**: 寻找F1分数($F1 = \frac{2PR}{P+R}$)最大值对应的阈值,此为精确率与召回率的最佳平衡点。 --- #### **4. 数据分布的影响** - **类别不平衡时的优势**: 当正负样本比例严重失衡(如1:100)时,PR曲线比ROC曲线更能反映模型的实际性能。 例如:负样本过多时,ROC曲线可能因高特异度(FPR低)而虚高,而PR曲线直接聚焦正样本的识别质量[^3]。 --- #### **代码示例(Python)** ```python from sklearn.metrics import precision_recall_curve, average_precision_score import matplotlib.pyplot as plt # 生成预测概率和真实标签 y_true = [0, 1, 1, 0, 1, 1, 0] y_score = [0.1, 0.4, 0.6, 0.3, 0.7, 0.8, 0.2] # 计算PR曲线数据 precision, recall, _ = precision_recall_curve(y_true, y_score) ap = average_precision_score(y_true, y_score) # 绘制PR曲线 plt.plot(recall, precision, label=f'PR Curve (AP={ap:.2f})') plt.xlabel('Recall') plt.ylabel('Precision') plt.legend() plt.show() ``` --- #### **典型场景对比** | 场景 | PR曲线表现 | 模型评估结论 | |--------------------------|------------------------------|---------------------------| | 类别平衡且模型优秀 | 曲线紧贴右上角,AP>0.9 | 性能优异 | | 类别不平衡但模型鲁棒 | 曲线显著高于基线,AP∈[0.6,0.8]| 需优化但可用 | | 负样本过多且模型失效 | 曲线接近基线,AP<0.3 | 需重新设计特征或采样策略 | --- ### 相关问题 1. [如何通过PR曲线选择最佳分类阈值?](#) 2. [类别不平衡时,除了PR曲线还有哪些评估方法?](#) 3. [AP(Average Precision)与AUC-ROC的区别是什么?](#) 4. [如何通过过采样/欠采样优化PR曲线表现?](#) [^1]: 基于ROC曲线PR曲线的分类模型性能评估 : 模型评估指标:P-R曲线和ROC曲线 [^4]: 机器学习指标评估:P-R曲线与ROC曲线,python sklearn实现
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值