机器学习算法题
题目说明
Elwin觉得自己在大学期间陷入了一个怪圈:不管他在学期初确立了多么严格的工作习惯,他最终
都会陷入到某个固定的工作节奏中。为此,Elwin请你帮他建立马尔科夫链模型,请你帮他分析分
析发生这种情况的原因。为了简化题目难度,我们可以认为Elwin在生活中只会干三件事:玩手
机,工作,学习。
Elwin给你提供了一些他的生活规律:
玩手机后,有90%的概率继续玩手机,7.5%的概率工作,2.5%的概率学习;
工作后,有15%的概率玩手机,80%的概率继续工作,5%的概率学习;
学习后,有25%的概率玩手机,25%的概率工作,50%的概率继续学习。
在第一个学期中,Elwin一开始时的工作习惯为:30%概率玩手机,40%概率工作,30%概率
学习。
在第二个学期中,Elwin一开始时的工作习惯为:10%概率玩手机,40%概率工作,50%概率
学习。
题目要求
使用C/C++语言完成
请勿抄袭
分析
马尔科夫链模型:就是事件的下一状态只跟当前状态有关,与过去的事件无关(无记忆)
分析:假设此时在做A事件,则下一时刻做A,B,C事件的概率分别为Paa,Pab,Pac,则再下一时刻做A事件的概率为P1=Paa*Paa+Pab*Pba+Pac*Pca,同理可得再下一时刻做B,C事件的概率P2,P3
观察P1,P2,P3式子,下一时刻概率可用矩阵表示
设一开始做A,B,C事件的概率为P1=[p1,p2,p3]
状态转移矩阵P=【Paa Pab Pac
Pba Pbb Pbc
Pca Pcb Pcc】
下一时刻概率可用P1*P计算出
通过不断的矩阵相乘,寻找题目中所说的”固定的生活节奏“。
代码实现
1.矩阵相乘
int matrixx ( const float* a, const float b[3][3], float* p )//a,b为相乘的矩阵,此处因为本题一直都是1x3与3x3的矩阵相乘,所以a为一维数组,p为相乘的结果
{
int i;
for ( i = 0; i < 3; i++ )
{
float stemp = 0;
for ( int j = 0; j < 3; j++ )
{
stemp = a[j] * b[j][i] + stemp;//前行乘后列
}
p[i] = stemp;
}
2.判断是否停止迭代
double diff = 0;
for ( int i = 0; i < 3; i++ )
{
double x = 0;
x = p[i] - a[i];
if ( x < 0 )
{
x = -x;
}
diff = diff + x;
}
if ( diff > 0 && diff < 0.0000001 )//以三个概率与前一时刻概率差的和小于0.0000001为界限
{
return 0;
}
else
{
return 1;
}
}
3.打印输出”固定的生活节奏“
void law ( float* a, const float b[3][3])//传入martixx函数所需的两个数组
{
float pn1[3] = {0, 0, 0};
int flag;
flag = matrixx ( a, b, pn1 );
while ( flag )
{
float pn2[3] = {0, 0, 0};
flag = matrixx ( pn1, b, pn2 ); //这里我也不知道咋回事,
//用pn1来接收相乘结果就会出错,
//必须一直用每一项都是0的数组来存。
for ( int i = 0; i < 3; i++ )
{
pn1[i] = pn2[i];
}
}
for ( int i = 0; i < 3; i++ )
{
printf ( "%f\t", pn1[i] );
}
printf("\n");
}
c完整代码
#include<stdio.h>
int matrixx ( const float* a, const float b[3][3], float* p )
{
int i;
for ( i = 0; i < 3; i++ )
{
float stemp = 0;
for ( int j = 0; j < 3; j++ )
{
stemp = a[j] * b[j][i] + stemp;
}
p[i] = stemp;
}
double diff = 0;
for ( int i = 0; i < 3; i++ )
{
double x = 0;
x = p[i] - a[i];
if ( x < 0 )
{
x = -x;
}
diff = diff + x;
}
if ( diff > 0 && diff < 0.0000001 )
{
return 0;
}
else
{
return 1;
}
}
void law ( float* a, const float b[3][3])
{
float pn1[3] = {0, 0, 0};
int flag;
flag = matrixx ( a, b, pn1 );
while ( flag )
{
float pn2[3] = {0, 0, 0};
flag = matrixx ( pn1, b, pn2 );
for ( int i = 0; i < 3; i++ )
{
pn1[i] = pn2[i];
}
}
for ( int i = 0; i < 3; i++ )
{
printf ( "%f\t", pn1[i] );
}
printf("\n");
}
int main()
{
float p1[3] = {0.3, 0.4, 0.3};
float p2[3] = {0.1, 0.4, 0.5};
float p[3][3] = {{0.9, 0.075, 0.025},
{0.15, 0.8, 0.05},
{0.25, 0.25, 0.5}
};/*90%的概率继续玩手机,7.5%的概率工作,2.5%的概率学习;
工作后,有15%的概率玩手机,80%的概率继续工作,5%的概率学习;
学习后,有25%的概率玩手机,25%的概率工作,50%的概率继续学习。
*/
law(p1,p);
law(p2,p);
return 0;
}
python numpy实现
import numpy as np
def check(n2, n1):
flag = 0
for i in range(3):
stem = n2[i] - n1[i]
if stem < 0:
stem = -stem
flag = flag + stem
if 0 < flag < 0.000000001:
return 0
else:
return 1
def end(p1,p):
n = np.dot(p1, p)
flag1 = check(n, p1)
while flag1:
n1 = n
n = np.dot(n, p)
flag1 = check(n, n1)
print(n)
p = np.array([[0.9, 0.075, 0.025], [0.15, 0.8, 0.05], [0.25, 0.25, 0.5]])
p1 = np.array([0.3, 0.4, 0.3])
p2 = np.array([0.1, 0.4, 0.5])
end(p1, p)
end(p2, p)