借kaldi来理解softmax

nnet-forward --feature-transform=final.feature_transform --no-softmax=false final.nnet scp:1.scp ark,t:output.ark.txt

final.feature_transform, final.nnet均由训练而来。final.feature_transform是对输入特征做转换,作为final.nnet的输入。

final.nnet是最后一层是softmax层,可以由–no-softmax这个参数来指定。

1.scp是输入特征文件的索引,为简单起见,只用一个特征文件。

ark,t:output.ark.txt将输出转成文本文件并输出到output.ark.txt中。这是一个m x n的矩阵,m是输入特征的帧数,n是final.nnet的输出状态数(这里是3000)。

选其中一帧的输出来理解softmax

sed -n '10p' output.ark.txt > 1.txt

(1)–no-softmax=false,做softmax

nnet-forward --feature-transform=final.feature_transform --no-softmax=false final.nnet scp:1.scp ark,t:output.ark.txt
sed -n '10p' output.ark.txt > 1.txt 
awk '{print NF}' 1.txt

显示是应该就是用nnet-info final.nnet看到的最后一层的值:3000

awk 'BEGIN{total=0.0}{for(i=1;i<=NF;i++)total += $i}END{print total}' 1.txt

这时应该看到就是1,说明softmax是起作用的。再看1.txt里应该是3000个特别小的数。

(2). –no-softmax=true,不做softmax

nnet-forward --feature-transform=final.feature_transform --no-softmax=true final.nnet scp:1.scp ark,t:output.ark.txt
sed -n '10p' output.ark.txt > 2.txt

再看2.txt中的内容,应该是非常大的不规整的值。大于1数有很多。

(3). 运行softmax算法将2.txt转成1.txt

算法描述:

    1. 找出3000个数中的最大值qMax。

    2. 将每一值转成Xi=exp(Xi-qMax), 并累加到qSum

    3. 将每一值转成Xi/qSum

用python实现:

import sys
import math

qList = open(sys.argv[1],'r').readline().split()
print len(qList)

qMax = 0.0
for i in range(len(qList)):
    cur = float(qList[i])
    if cur>qMax:
        qMax = cur

print qMax
qSum = 0.0
for i in range(len(qList)):
    cur = float(qList[i])
    qList[i] = math.exp(cur-qMax)
    qSum += qList[i]

print qSum
fout = open(sys.argv[2],'w')
for i in range(len(qList)):
    qList[i] = qList[i]/qSum
    fout.write('%g\t' % qList[i])

fout.write('\n')
fout.close()

以上只是为了描述算法,效率不做考虑。

python softmax.py 2.txt 2_sm.txt

(4)比较1.txt, 2_sm.txt的值,日常接近,小有差异可能是python的数据转换带来的,对于算法的正确性没有影响。


kaldi中的代码实现:

./src/matrix/kaldi-matrix.cc

template<typename Real>
Real MatrixBase<Real>::ApplySoftMax() {
  Real max = this->Max(), sum = 0.0;
  // the 'max' helps to get in good numeric range.
  for (MatrixIndexT i = 0; i < num_rows_; i++)
    for (MatrixIndexT j = 0; j < num_cols_; j++)
      sum += ((*this)(i, j) = Exp((*this)(i, j) - max));
  this->Scale(1.0 / sum);
  return max + Log(sum);
}

cannot find -lgcc_s

问题:

/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-redhat-linux/4.4.7/libgcc_s.so when searching for -lgcc_s
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-redhat-linux/4.4.7/libgcc_s.so when searching for -lgcc_s
/usr/bin/ld: cannot find -lgcc_s

解决办法:

yum install -y libgcc.i686

用链表实现基数排序

#include <stdio.h>
#include <stdlib.h>
typedef struct Node *PtrToNode;
typedef PtrToNode List;
struct Node{
	int value;
    PtrToNode Next;
};
enum Index {Gewei=1,Shiwei=10,Baiwei=100};
typedef enum Index Index;

void Delete(PtrToNode p[]);
void PrintList(PtrToNode p[]);
void CopyNode2Arr(PtrToNode p[],int a[]);
void LoadArr2NodeList(PtrToNode p[],int a[],int length,Index nIndex);
int *Sort(PtrToNode p[],int a[],int length, int iterNum);

void LoadArr2NodeList(PtrToNode p[],int a[],int length,Index nIndex)
{
	int i;
	int bitNum;
	PtrToNode tmpCell,yun;

	for(i=0;i<length;i++){
		bitNum = a[i] /nIndex % 10;
		tmpCell = malloc(sizeof(struct Node));
		tmpCell->value = a[i];
		tmpCell->Next = NULL;
		if(p[bitNum]->Next == NULL)
			p[bitNum]->Next = tmpCell;
		else
		{
			yun = p[bitNum];
			while(yun->Next != NULL)
				yun = yun->Next;
			yun->Next = tmpCell;
		}
	}

}

void CopyNode2Arr(PtrToNode p[],int a[]){
	PtrToNode yun;
	int i=0;
	int j;
	for(j=0;j<10;j++){
		if(p[j]->Next != NULL){
			yun = p[j];
			while(yun->Next != NULL){
				yun = yun->Next;
				a[i] = yun->value;
				i++;
			}
		}
	}
}

void PrintList(PtrToNode p[])
{
	int i;
	PtrToNode yun;
	for (i=0;i<10;i++){
		printf("%d:",i);
		if(p[i]->Next != NULL){
			yun = p[i];
			while(yun->Next != NULL){
				yun = yun->Next;
				printf("%d\t",yun->value);
			}
		}
		printf("\n");
	}
	printf("\n");
}

void Delete(PtrToNode p[])
{
	PtrToNode yun,tmpCell;
	int i;

	for(i=0;i<10;i++){
		yun = p[i]->Next;
		p[i]->Next = NULL;
		while(yun != NULL){
			tmpCell = yun->Next;
			free(yun);
			yun = tmpCell;
		}
	}
}

/*
 * @ length: length of a
 * @ iterNum: wei num of max
 */
int *Sort(PtrToNode p[],int a[],int length, int iterNum)
{
	LoadArr2NodeList(p,a,length,Gewei);
	PrintList(p);
	CopyNode2Arr(p,a);
	Delete(p);
	
	LoadArr2NodeList(p,a,length,Shiwei);
	PrintList(p);
	CopyNode2Arr(p,a);
	Delete(p);

	LoadArr2NodeList(p,a,length,Baiwei);
	PrintList(p);
	CopyNode2Arr(p,a);
	Delete(p);

	return a;
}

int
main(int argc, char *argv[])
{
	PtrToNode p[10];
	int i;
	PtrToNode tmp;
	int *result;
	int a[12] = {2,512,34,315,256,65,108,99,11,234,78,89};
	for(i=0;i<10;i++){
		tmp = malloc(sizeof(PtrToNode));
		tmp->Next = NULL;
		p[i] = tmp;
	}
	result = Sort(p,a,12,3);
	for(i=0;i<12;i++)
		printf("%d\t",*(result+i));
	printf("\n");
}
结果如下:
0:
1:11	
2:2	512	
3:
4:34	234	
5:315	65	
6:256	
7:
8:108	78	
9:99	89	

0:2	108	
1:11	512	315	
2:
3:34	234	
4:
5:256	
6:65	
7:78	
8:89	
9:99	

0:2	11	34	65	78	89	99	
1:108	
2:234	256	
3:315	
4:
5:512	
6:
7:
8:
9:

2	11	34	65	78	89	99	108	234	256	315	512

CentOS6.2自动发邮件

需求:

    1.    每天自动统计信息。

    2.    每天自动发邮件给某些地址

难点:

    1.    自动任务定义

    2.    自动发送的配置

步骤:

    1.    把脚本加入到crontab中

crontab -e
0 8 * * * /home/orangespeech/autoReport.sh

    以上命令是每天8点自动运行autoReport.sh

    2.    安装sendmail

yum -y install sendmail

    3.    配置/etc/mail/sendmail.mc

    更改

    LOCAL_DOMAIN(`localhost.localdomain’)dnl

    为

    LOCAL_DOMAIN(`smtp.xxx.com’)dnl

    4.    配置/etc/hosts

    更改 127.0.0.1和::1两行为

    127.0.0.1   stmp.xxx.com localhost localhost.localdomain localhost4 localhost4.localdomain4

    ::1             stmp.xxx.com localhost localhost.localdomain localhost4 localhost4.localdomain4

    5.    把发送邮件的命令放在autoReport.sh中

echo "test" | mail -s "Report" sss@xxx.com

    以上命令是发送一个主题是”Report”,内容为”test”的邮件给sss@xxx.com

Bravo

如果收不到邮件,看/var/log/maillog

<转>最大似然估计和最大后验概率

极大似然估计和贝叶斯估计分别代表了频率派和贝叶斯派的观点。频率派认为,参数是客观存在的,只是未知而矣。因此,频率派最关心极大似然函数,只要参数求出来了,给定自变量X,Y也就固定了,极大似然估计如下所示:

D表示训练数据集,是模型参数

相反的,贝叶斯派认为参数也是随机的,和一般随机变量没有本质区别,正是因为参数不能固定,当给定一个输入x后,我们不能用一个确定的y表示输出结果,必须用一个概率的方式表达出来,所以贝叶斯学派的预测值是一个期望值,如下所示:

其中x表示输入,y表示输出,D表示训练数据集,是模型参数

  该公式称为全贝叶斯预测。现在的问题是如何求(后验概率),根据贝叶斯公式我们有:

  可惜的是,上面的后验概率通常是很难计算的,因为要对所有的参数进行积分,不能找到一个典型的闭合解(解析解)。在这种情况下,我们采用了一种近似的方法求后验概率,这就是最大后验概率。

  最大后验概率和极大似然估计很像,只是多了一项先验分布,它体现了贝叶斯认为参数也是随机变量的观点,在实际运算中通常通过超参数给出先验分布。

 
从以上可以看出,一方面,极大似然估计和最大后验概率都是参数的点估计。在频率学派中,参数固定了,预测值也就固定了。最大后验概率是贝叶斯学派的一种近
似手段,因为完全贝叶斯估计不一定可行。另一方面,最大后验概率可以看作是对先验和MLE的一种折衷,如果数据量足够大,最大后验概率和最大似然估计趋向
于一致,如果数据为0,最大后验仅由先验决定。

Centos支持40T磁盘阵列MD1200

最近数据增长太快,靠服务器存储已经不能满足需求了。从Dell买了一台MD1200,准备级连到一台数据服务器上,把大量备份的数据存储在MD1200上。MD1200配备12块4T的SAS硬盘,做完RAID5 后有40T容量。如果以后要做扩展,只需要在MD1200后再级连存储服务器。

硬件环境:Dell 服务器PowerEdge R720 + PowerVault MD1200

软件环境:R720是CentOS 6.5

操作步骤:

1.把MD1200带的PERC H810板卡插到R720上的Riser2/Riser3。
2.用2根SAS数据线连将R720和MD1200连起来,MD1200上插IN口,R720插PERC H810上。
3.通电->启动->Ctrl+R进入Raid设置。
4.会看到两个,系统自带的和新装的H810,选H810,就进入常见的Raid设置界面。
5.设置RAID5。
6.格式化磁盘。因为整个磁盘空间超过2T,不能mkfs格式。 

parted /dev/sdb
mklabel gpt
mkpart primary 0 -1
quit
mkfs -t ext4 /dev/sdb1 或者  mkfs.ext4  /dev/sdc1 

以上最后一步会报错

“mke2fs 1.41.12 (17-May-2010)

mkfs.ext4: Size of device /dev/sdc1 too big to be expressed in 32 bits using a blocksize of 4096.”

出错的原因:e2fsprogs版本低

7.下载1.42版本

wget http://downloads.sourceforge.net/project/e2fsprogs/e2fsprogs/v1.42.7/e2fsprogs-1.42.7.tar.gz -O e2fsprogs-1.42.7.tar.gz

 8. 编译安装

#tar -xzvf e2fsprogs-1.42.7.tar.gz
# cd e2fsprogs-1.42.7
# mkdir build
# cd build
# ../configure
# make
# make install

 9.修改配置
vi /etc/mke2fs.conf
在ext4块添加auto_64-bit_support = 1

ext4 = {
features = has_journal,extent,huge_file,flex_bg,uninit_bg,dir_nlink,extra_isize
auto_64-bit_support = 1      ###新增加行,告诉系统使用64位方式进行格式化。避免mkfs.ext4直接报错。
inode_size = 256
}

10. 格式化

#mke2fs -O 64bit,has_journal,extents,huge_file,flex_bg,uninit_bg,dir_nlink,extra_isize -i 4194304 /dev/sdb1

11. mount

#mout /dev/sdb1 /mnt

12. df -h查看

完成,bravo!

开启一个新的历程

每天的生活都一样,每天的生活都不一样; 我们在不断失去,我们在不断获得;我们一直走向终点,我们一直开始新的起点。如阿甘所言,“生活就像一盒巧克力,你永远不会知道你将得到什么。”