发布时间:2025-12-10 19:31:58 浏览次数:10
【darknet源码解析-04】matrix.h 和 matrix.c「建议收藏」本系列为darknet源码解析,本次解析src/matrix.h与src/matrix.c两个。matrix.h中的包含的代码如下:#ifndefMATRIX_H#defineMATRIX_H#include”darknet.h”//将矩阵m中的数据拷贝到内存中matrixcopy_matrix(matrixm);//可视化voidprint_mat…
本系列为darknet源码解析,本次解析src/matrix.h 与 src/matrix.c 两个。
matrix.h 中的包含的代码如下:
#ifndef MATRIX_H#define MATRIX_H#include "darknet.h"// 将矩阵m中的数据拷贝到内存中matrix copy_matrix(matrix m);// 可视化void print_matrix(matrix m);//从矩阵中采样m行数据,返回采样后的结果;matrix hold_out_matrix(matrix *m, int n);// 矩阵的行数和列数进行resize操作,resize矩阵大小是size * sizematrix resize_matrix(matrix m, int size);//获取矩阵中某一列数据,并把该列删除掉float *pop_column(matrix *m, int c);#endif 是否还在为Ide开发工具频繁失效而烦恼,来吧关注以下公众号获取最新激活方式。亲测可用!
【正版授权,激活自己账号】:Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】:官方授权 正版激活 自己使用,支持Jetbrains家族下所有IDE…
首先,我们分析matrix.h 中的源码,基础数据结构list 定义在 darknet.h 中,其定义如下:
typedef struct matrix{ int rows, cols; // 行数,列数 float **vals; // 二维float数组} matrix; matrix.c 中函数的详细分析如下,
#include "matrix.h"#include "utils.h"#include "blas.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#include <math.h>/*** 释放矩阵的存储空间* @param matrix 待释放存储空间矩阵 m*/void free_matrix(matrix m){int i;// 逐行释放存储空间;for(i = 0; i < m.rows; ++i) free(m.vals[i]);free(m.vals);}/*** emmm...... 暂时不能理解这波操作,先空在这里,看上层怎么用???* @param truth 矩阵* @param guess* @param k 取top的个数* @return 查找的准确率*/float matrix_topk_accuracy(matrix truth, matrix guess, int k){// 申请k个int类型存储空间,int *indexes = calloc(k, sizeof(int));int n = truth.cols;// n 保存truth矩阵的列数int i,j;int correct = 0;for(i = 0; i < truth.rows; ++i){// top_K 查找guess.vals[i] 数组中 top-k 个, index保存在 indexestop_k(guess.vals[i], n, k, indexes);// 逐一遍历这top-k个数据for(j = 0; j < k; ++j){int class = indexes[j]; // 取indexif(truth.vals[i][class]){ //对应 truth.vals[i][class] 位置是否非0++correct; // 非0 就表示满足break;}}}free(indexes); // 释放indexreturn (float)correct/truth.rows; // 返回比例,看样子是准确度。}/*** 矩阵与常数乘法操作,将矩阵m中每个元素都放大scale倍* @param m 矩阵* @param scale 乘子*/void scale_matrix(matrix m, float scale){int i,j;for(i = 0; i < m.rows; ++i){for(j = 0; j < m.cols; ++j){m.vals[i][j] *= scale;}}}/*** 矩阵的行数和列数进行resize操作,resize矩阵大小是size * size* @param m 待调整矩阵* @param size 调整后的矩阵大小为 size * size* @return resize后的矩阵*/matrix resize_matrix(matrix m, int size){int i;if (m.rows == size) return m; // 如果矩阵行数不发现变化,则不做任何调整;if (m.rows < size) { // 调整后矩阵行数变多/* 函数名:recalloc函数原型:extern void *realloc (void *mem_address, unsigned int newsize);函数功能:动态调整内存,先判断当前的指针是否有足够的连续空间,如果有,则扩大mem_address指向的地址,并且将mem_address返回,如果空间不够,先按照newsize指定的大小分配空间,将原有数据全部拷贝到新分配的内存区域,而后对原来meme_address所指向的内存区域进行释放【这里是自动释放,不需要手动释放】,同时返回新分配内存区域的首地址。如果失败则返回空指针NULL;*/m.vals = realloc(m.vals, size*sizeof(float*)); // 重新申请内存空间for (i = m.rows; i < size; ++i) {m.vals[i] = calloc(m.cols, sizeof(float)); // 每一行的存储空间也要重新申请,每一行保存size 个数据}} else if (m.rows > size) { // 调整后矩阵行数减少for (i = size; i < m.rows; ++i) { // 释放多余的存储空间free(m.vals[i]); }m.vals = realloc(m.vals, size*sizeof(float*)); // 分配每一行存储空间,每一行保存size 个数据}m.rows = size;return m; // m是一个size*size 大小的矩阵}/*** 两个矩阵的加法操作* @param from 矩阵* @param to 矩阵* 最后结果写入到矩阵 to 中*/void matrix_add_matrix(matrix from, matrix to){assert(from.rows == to.rows && from.cols == to.cols);int i,j;for(i = 0; i < from.rows; ++i){for(j = 0; j < from.cols; ++j){to.vals[i][j] += from.vals[i][j];}}}/*** 将矩阵m中的数据拷贝到内存中* @param m 待拷贝数据* @return 返回存储在内存中矩阵*/matrix copy_matrix(matrix m){matrix c = {0};c.rows = m.rows;c.cols = m.cols;c.vals = calloc(c.rows, sizeof(float *));int i;for(i = 0; i < c.rows; ++i){c.vals[i] = calloc(c.cols, sizeof(float));// copy_cpu() 定义在 blas.h 中// void copy_cpu(int N, float *X, int INCX, float *Y, int INCY);/* blas.c 中* void copy_cpu(int N, float *X, int INCX, float *Y, int INCY){int i;for(i = 0; i < N; ++i) Y[i*INCY] = X[i*INCX];}*/// 将矩阵m的内容拷贝到矩阵c中copy_cpu(c.cols, m.vals[i], 1, c.vals[i], 1);}return c;}/*** 矩阵初始化* @param rows 行数* @param cols 列数* @return 初始化结果*/matrix make_matrix(int rows, int cols){int i;matrix m;m.rows = rows;m.cols = cols;m.vals = calloc(m.rows, sizeof(float *));// 申请存储空间for(i = 0; i < m.rows; ++i){m.vals[i] = calloc(m.cols, sizeof(float));}return m;}/*** 从矩阵中采样m行数据,返回采样后的结果;* @param m 待采样的数据* @param n 抽取的行数* @return 采样后的结果;*/matrix hold_out_matrix(matrix *m, int n){int i;matrix h;h.rows = n;h.cols = m->cols;h.vals = calloc(h.rows, sizeof(float *)); //申请新矩阵的存储空间for(i = 0; i < n; ++i){int index = rand()%m->rows; // 随机抽取一行h.vals[i] = m->vals[index];m->vals[index] = m->vals[--(m->rows)]; // 把最后一行的数据覆盖到 index行上}return h;}/*** 获取矩阵中某一列数据,并把该列删除掉* @param m 待删除矩阵* @param c 列的index* @return 返回指定列*/float *pop_column(matrix *m, int c){//float *col = calloc(m->rows, sizeof(float));int i, j;for(i = 0; i < m->rows; ++i){col[i] = m->vals[i][c]; // 逐行获取第c列for(j = c; j < m->cols-1; ++j){m->vals[i][j] = m->vals[i][j+1]; // 将c+1 到 m.cols-1列向左平移}}--m->cols; // 列数自减1return col;}/*** 读取文件,并将文件中的数据加载到矩阵matrix中* @param filename 文件的存储位置* @return 矩阵*/matrix csv_to_matrix(char *filename){FILE *fp = fopen(filename, "r");if(!fp) file_error(filename); // 如果不能打印文件,保存退出程序matrix m;m.cols = -1;char *line;int n = 0;int size = 1024;m.vals = calloc(size, sizeof(float*));while((line = fgetl(fp))){ // fgetl 读取文件中一行数据// 统计字符串中有多少个 ',' 字符和 '\0', 遇到第一个'\0'字符结束;// 相当于统计line中包含多少个数据,其实这就是矩阵的列数if(m.cols == -1) m.cols = count_fields(line);if(n == size){ //如果处理到第1024行,需要重新扩充 m.vals的存储空间size *= 2;m.vals = realloc(m.vals, size*sizeof(float*));}m.vals[n] = parse_fields(line, m.cols); // 解析字符数组中m.cols个float小数,返回是一个float类型指针free(line); // 释放line存储空间++n; //统计处理行数}m.vals = realloc(m.vals, n*sizeof(float*)); // 之前开辟的空间是1024的整数倍,此时需要根据n来实际分配内存空间m.rows = n;return m; // 返回结果}/*** 可视化打印矩阵m,打印格式按照csv格式* @param m*/void matrix_to_csv(matrix m){int i, j;for(i = 0; i < m.rows; ++i){for(j = 0; j < m.cols; ++j){if(j > 0) printf(",");printf("%.17g", m.vals[i][j]); //自动选择合适的表示法输出}printf("\n");}}/*** 可视化打印矩阵m* @param m*/void print_matrix(matrix m){int i, j;printf("%d X %d Matrix:\n",m.rows, m.cols); //打印行和列数printf(" __");for(j = 0; j < 16*m.cols-1; ++j) printf(" ");printf("__ \n");printf("| ");for(j = 0; j < 16*m.cols-1; ++j) printf(" ");printf(" |\n");for(i = 0; i < m.rows; ++i){printf("| ");for(j = 0; j < m.cols; ++j){printf("%15.7f ", m.vals[i][j]);}printf(" |\n");}printf("|__");for(j = 0; j < 16*m.cols-1; ++j) printf(" ");printf("__|\n");} 完,