如何理解计算机视觉损失函数?

如何理解计算机视觉损失函数?,第1张

三元组,第1列是行号,第2列是列号,第3列是非零元素的值。

三元组是指形如((x,y),z)的集合(这就是说,三元组是这样的偶,其第一个射影亦是一个偶),常简记为(x,y,z)。

三元组是:计算机专业的一门公共基础课程——数据结构里的概念。主要是用来存储稀疏矩阵的一种压缩方式,也叫三元组表。

假设以顺序存储结构来表示三元组表(triple table),则得到稀疏矩阵的一种压缩存储方式,即三元组顺序表,简称三元组表。

visual studio下编译通过,测试结果正确,万一VC6编译不过请用TC20
//稀疏矩阵就是只记录非零元的位置和值,适合处理0比较多的矩阵
#include <stdioh>
#include <malloch>
#define MAXSIZE 10
typedef struct node
{
int i,j,value; //i为行下标,j为列下标,value为该处的值
}NODE;
typedef struct mat
{
int mv,mc,mt; //mv为行数,mc为列数,mt为非零元个数
NODE v[MAXSIZE];
}MAT;
//view为输出稀疏矩阵
void view(MAT a)
{
printf("矩阵的三元组表示:\n");
printf("i j v\n");
for(int k=0;k<a->mt;k++)
printf("%-6d%-6d%-6d\n",a->v[k]i,a->v[k]j,a->v[k]value);

}
//init为输入一个矩阵并存为稀疏矩阵
void init(MAT a)
{
int k=0; //非零元的序号
//for(k=0;k<MAXSIZE;k++)
// a->v[k]value=0; //先都初始化为零
a->mt=0;
printf("请输入行数和列数:\n");
scanf("%d%d",&a->mv,&a->mc);
printf("\n请依次输入矩阵的各个元素的值:\n");
for(int m=1;m<=a->mv;m++)
for(int n=1;n<=a->mc;n++)
{
int t;
scanf("%d",&t);
//如果t为非零元,存入v[k]中
if(t!=0)
{
a->v[k]i=m;
a->v[k]j=n;
a->v[k]value=t;
a->mt++;
k++;
}
}
}
//矩阵a转置后存入矩阵b
void change(MAT a,MAT b)
{
b->mv=a->mc;
b->mc=a->mv;
b->mt=a->mt;
if(a->mt)
{
int p=0,q=0;
for(int n=1;n<=a->mc;n++)
for(int p=0;p<=a->mc;p++)
{
if(a->v[p]j==n) //v[p]是第n列的非零元
{
b->v[q]i=a->v[p]j;
b->v[q]j=a->v[p]i;
b->v[q]value=a->v[p]value;
q++;
}
}
}
}
void main()
{
MAT a,b;
b=(MAT )malloc(sizeof(MAT));
a=(MAT )malloc(sizeof(MAT));
init(a);
view(a);
change(a,b);
view(b);
}

只写了相加方法,相减类似,乘法需要另外处理
/

表示矩阵的单个元素的三元组,row行号,col列号,val元素值
compareTo方法比较两个元素位置(按行号优先)返回-1(位置在之前),0(相同位置),1(位置在之后)
/
class Trituple implements Comparable<Trituple>
{
int row;
int col;
double val;
public Trituple(int row, int col, double val)
{
thisrow = row;
thiscol = col;
thisval = val;
}
public Trituple(Trituple t, double val)
{
this(trow, tcol, val);
}
public Trituple(Trituple t)
{
this(trow, tcol, tval);
}
public int compareTo(Trituple t)
{
if (row < trow)
{
return -1;
}
else
{
if (row == trow)
{
if (col < tcol)
{
return -1;
}
else
{
if (col == tcol)
{
return 0;
}
else
{
return 1;
}
}
}
else
{
return 1;
}
}
}
}
/

表示稀疏矩阵,rowNum行数,colNum列数,trituples三元组的顺序表
add方法返回一个新的稀疏矩阵,check检查两个相加矩阵的规模是否相同

/
class SparseMatrix
{
int rowNum;
int colNum;
List<Trituple> trituples;
public SparseMatrix(List<Trituple> list, int row, int col)
{
thistrituples = list;
thisrowNum = row;
thiscolNum = col;
}
public SparseMatrix add(SparseMatrix matrix) throws IllegalArgumentException
{
if (check(matrix) == false)
{
throw new IllegalArgumentException("invalid matrix dimentions~");
}
List<Trituple> list = new ArrayList<Trituple>();
int loop = trituplessize() + matrixtrituplessize();
int index = 0, index0 = 0;
while (loop > 0)
{
Trituple t = trituplesget(index);
Trituple t0 = matrixtrituplesget(index0);
if (tcompareTo(t0) < 0)
{
listadd(new Trituple(t));
index++;
loop--;
}
else
{
if (tcompareTo(t0) == 0)
{
listadd(new Trituple(t, tval + t0val));
index++;
index0++;
loop -= 2;
}
else
{
listadd(new Trituple(t0));
index0++;
loop--;
}
}
}
SparseMatrix sm = new SparseMatrix(list, rowNum, colNum);
return sm;
}
private boolean check(SparseMatrix matrix)
{
if (thisrowNum != matrixrowNum || thiscolNum != matrixcolNum)
{
return false;
}
return true;
}
}

#include <iostream>
#include <iomanip>
using namespace std;
const int MAXSIZE=100; // 定义非零元素的对多个数
const int MAXROW=10; // 定义数组的行数的最大值
typedef struct { // 定义三元组的元素
int i,j;
int e;
}Triple;
typedef struct { // 定义普通三元组对象
Triple data[MAXSIZE+1];
int mu,nu,tu;
}TSMatrix;
typedef struct { // 定义带链接信息的三元组对象
Triple data[MAXSIZE+2];
int rpos[MAXROW+1];
int mu,nu,tu;
}RLSMatrix;
template <class P>
bool InPutTSMatrix(P & T,int y){ //输入矩阵,按三元组格式输入
cout<<"输入矩阵的行,列和非零元素个数:"<<endl;
cin>>Tmu>>Tnu>>Ttu;
cout<<"请输出非零元素的位置和值:"<<endl;
int k=1;
for(;k<=Ttu;k++)
cin>>Tdata[k]i>>Tdata[k]j>>Tdata[k]e;
return true;
}
template <class P>
bool OutPutSMatrix(P T){ // 输出矩阵,按标准格式输出
int m,n,k=1;
for(m=0;m<Tmu;m++){
for(n=0;n<Tnu;n++){
if((Tdata[k]i-1)==m&&(Tdata[k]j-1)==n){
coutwidth(4);
cout<<Tdata[k++]e;}
else{
coutwidth(4); cout<<"0"; }
}
cout<<endl;
}
return true;
}
// 求矩阵的转置矩阵
bool TransposeSMatrix( ){
TSMatrix M,T; //定义预转置的矩阵
InPutTSMatrix(M, 0); //输入矩阵
int num[MAXROW+1];
int cpot[MAXROW+1]; // 构建辅助数组
int q,p,t;
Ttu=Mtu; Tmu=Mnu; Tnu=Mmu;
if(Ttu){
for(int col=1;col<=Mnu;col++) num[col]=0;
for(t=1;t<=Mtu;t++) ++num[Mdata[t]j];
cpot[1]=1;
for(int i=2;i<=Mnu;i++) cpot[i]=cpot[i-1]+num[i-1]; // 求出每一列中非零元素在三元组中出现的位置
for(p=1;p<=Mtu;p++){
col=Mdata[p]j; q=cpot[col];
Tdata[q]i=col; Tdata[q]j=Mdata[p]i;
Tdata[q]e=Mdata[p]e; ++cpot[col];
}
}
cout<<"输入矩阵的转置矩阵为"<<endl;
OutPutSMatrix(T);
return true;
}
bool Count(RLSMatrix &T)
{
int num[MAXROW+1];
for(int col=1;col<=Tmu;col++) num[col]=0;
for(col=1;col<=Ttu;col++) ++num[Tdata[col]i];
Trpos[1]=1;
for(int i=2;i<=Tmu;i++) Trpos[i]=Trpos[i-1]+num[i-1]; // 求取每一行中非零元素在三元组中出现的位置
return true;
}
// 两个矩阵相乘
bool MultSMatrix ( ){
RLSMatrix M,N,Q; // 构建三个带“链接信息”的三元组表示的数组
InPutTSMatrix(M,1); // 用普通三元组形式输入数组
InPutTSMatrix(N,1);
Count(M); Count(N);
if(Mnu!=Nmu) return false;
Qmu=Mmu; Qnu=Nnu; Qtu=0; // Q初始化
int ctemp[MAXROW+1]; // 辅助数组
int arow,tp,p,brow,t,q,ccol;
if(MtuNtu){ // Q是非零矩阵
for( arow=1;arow<=Mmu;arow++){
///memset(ctemp,0,Nnu);
for(int x=1;x<=Nnu;x++) // 当前行各元素累加器清零
ctemp[x]=0;
Qrpos[arow]=Qtu+1; // 当前行的首个非零元素在三元组中的位置为此行前所有非零元素+1
if(arow<Mmu) tp=Mrpos[arow+1];
else tp=Mtu+1;
for(p=Mrpos[arow];p<tp;p++){ // 对当前行每个非零元素进行 *** 作
brow=Mdata[p]j; // 在N中找到i值也 *** 作元素的j值相等的行
if(brow<Nmu) t=Nrpos[brow+1];
else t=Ntu+1;
for(q=Nrpos[brow];q<t;q++){ // 对找出的行当每个非零元素进行 *** 作
ccol=Ndata[q]j;
ctemp[ccol] += Mdata[p]eNdata[q]e; // 将乘得到对应值放在相应的元素累加器里面
}
}
for(ccol=1;ccol<=Qnu;ccol++) // 对已经求出的累加器中的值压缩到Q中
if(ctemp[ccol]){
if(++Qtu>MAXSIZE) return false;
Qdata[Qtu]e=ctemp[ccol];
Qdata[Qtu]i=arow;
Qdata[Qtu]j=ccol;
}
}
}
OutPutSMatrix(Q);
return true;
}
typedef struct OLNode{ // 定义十字链表元素
int i,j;
int e;
struct OLNode right,down; // 该非零元所在行表和列表的后继元素
}OLNode,OLink;
typedef struct{ // 定义十字链表对象结构体
OLink rhead,chead;
int mu,nu,tu; // 系数矩阵的行数,列数,和非零元素个数
}CrossList;
bool CreateSMatrix_OL(CrossList & M){ // 创建十字链表
int x,y,m;
cout<<"请输入矩阵的行,列,及非零元素个数"<<endl;
cin>>Mmu>>Mnu>>Mtu;
if(!(Mrhead=(OLink)malloc((Mmu+1)sizeof(OLink)))) exit(0);
if(!(Mchead=(OLink)malloc((Mnu+1)sizeof(OLink)))) exit(0);
for(x=0;x<=Mmu;x++)
Mrhead[x]=NULL; // 初始化各行,列头指针,分别为NULL
for(x=0;x<=Mnu;x++)
Mchead[x]=NULL;
cout<<"请按三元组的格式输入数组:"<<endl;
for(int i=1;i<=Mtu;i++){
cin>>x>>y>>m; // 按任意顺序输入非零元,(普通三元组形式输入)
OLink p,q;
if(!(p=(OLink)malloc(sizeof(OLNode)))) exit(0); // 开辟新节点,用来存储输入的新元素
p->i=x; p->j=y; p->e=m;
if(Mrhead[x]==NULL||Mrhead[x]->j>y){
p->right=Mrhead[x]; Mrhead[x]=p;
}
else{
for(q=Mrhead[x];(q->right)&&(q->right->j<y);q=q->right); // 查找节点在行表中的插入位置
p->right=q->right; q->right=p; // 完成行插入
}
if(Mchead[y]==NULL||Mchead[y]->i>x){
p->down=Mchead[y]; Mchead[y]=p;
}
else{
for(q=Mchead[y];(q->down)&&(q->down->i<x);q=q->down); // 查找节点在列表中的插入位置
p->down=q->down; q->down=p; // 完成列插入
}
}
return true;
}
bool OutPutSMatrix_OL(CrossList T){ // 输出十字链表,用普通数组形式输出
for(int i=1;i<=Tmu;i++){
OLink p=Trhead[i];
for(int j=1;j<=Tnu;j++){
if((p)&&(j==p->j)){
cout<<setw(3)<<p->e; p=p->right;
}
else
cout<<setw(3)<<"0";
}
cout<<endl;
}
return true;
}
//矩阵的加法
bool AddSMatrix(){
CrossList M,N; // 创建两个十字链表对象,并初始化
CreateSMatrix_OL(M);
CreateSMatrix_OL(N);
cout<<"输入的两矩阵的和矩阵为:"<<endl;
OLink pa,pb,pre ,hl[MAXROW+1]; //定义辅助指针,pa,pb分别为M,N当前比较的元素,pre为pa的前驱元素
for(int x=1;x<=Mnu;x++) hl[x]=Mchead[x];
for(int k=1;k<=Mmu;k++){ // 对M的每一行进行 *** 作
pa=Mrhead[k]; pb=Nrhead[k]; pre=NULL;
while(pb){ // 把N中此行的每个元素取出,
OLink p;
if(!(p=(OLink)malloc(sizeof(OLNode)))) exit(0); // 开辟新节点,存储N中取出的元素
p->e=pb->e; p->i=pb->i; p->j=pb->j;
if(NULL==pa||pa->j>pb->j){ // 当M此行已经检查完或者pb因该放在pa前面
if(NULL==pre)
Mrhead[p->i]=p;
else
pre->right=p;
p->right=pa; pre=p;
if(NULL==Mchead[p->j]){ // 进行列插入
Mchead[p->j]=p; p->down=NULL;
}
else{
p->down=hl[p->j]->down; hl[p->j]->down=p;
}
hl[p->j]=p;
pb=pb->right;
}
else
if((NULL!=pa)&&pa->j<pb->j){ // 如果此时的pb元素因该放在pa后面,则取以后的pa再来比较
pre=pa; pa=pa->right;
}
else
if(pa->j==pb->j){ // 如果pa,pb位于同一个位置上,则将值相加
pa->e += pb->e;
if(!pa->e){ // 如果相加后的和为0,则删除此节点,同时改变此元素坐在行,列的前驱元素的相应值
if(NULL==pre) // 修改行前驱元素值
Mrhead[pa->i]=pa->right;
else
pre->right=pa->right;
p=pa; pa=pa->right;
if(Mchead[p->j]==p) Mchead[p->j]=hl[p->j]=p->down; // 修改列前驱元素值
else
hl[p->j]->down=p->down;
free(p); pb=pb->right;
}
else{
pa=pa->right; pb=pb->right;
}
}
}
}
OutPutSMatrix_OL(M);
return true;
}
int main(){
coutfill('');
cout<<setw(80)<<'';
coutfill(' ');
// system("color 0C");
cout<<setw(50)<<"欢迎使用矩阵运算程序"<<endl; //输出头菜单
coutfill('');
cout<<setw(80)<<'';
coutfill(' ');
cout<<"请选择要进行的 *** 作:"<<endl;
cout<<"1:矩阵的转置。"<<endl;
cout<<"2:矩阵的加(减)法。"<<endl;
cout<<"3:矩阵的乘法。"<<endl;
cout<<"4:推出程序。"<<endl;
char c=getchar();
if(c=='1')
TransposeSMatrix( ); //调用矩阵转置函数
else
if(c=='2')
AddSMatrix(); //调用矩阵相加函数
else
if(c=='3')
MultSMatrix (); //调用矩阵相乘函数
else
exit(0); //退出
return 0;
}
谢谢

三元组表行数是从1开始算,首先自己输入一个矩阵(这是比较麻烦的方法)或利用伪随机数产生一个稀疏矩阵(这是我用的方法)然后利用循环对该矩阵进行扫描,将非零元素的行列值以及非零元素的值存入线性表。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/yw/12944091.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-29
下一篇 2023-05-29

发表评论

登录后才能评论

评论列表(0条)

保存