2013年9月20日星期五

Socket网络编程(3)--两端通信 - wolfy

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
Socket网络编程(3)--两端通信 - wolfy  阅读原文»

上篇博文:http://www.cnblogs.com/wolf-sun/p/3329558.html

介绍了客户端连接服务端,一对一,多对一的情况,下面实现服务器接收消息的功能。LZ这些弄的比较慢,也是边学习,边动手实现的。具体步骤在注释中写的比较清楚,不懂的可以留言,LZ会尽快回复。共同学习,共同进步。

接收消息时机

什么时候接收消息?当服务器开始监听,有客户端连接,并且连接成功,此时负责通信的Socket已经创建,此时就可以接收消息了,可以通过Socket的Receive()方法接收消息。

1 // 摘要:
2 // 从绑定的 System.Net.Sockets.Socket 套接字接收数据,将数据存入接收缓冲区。
3 //
4 // 参数:
5 // buffer:
6 // System.Byte 类型的数组,它是存储接收到的数据的位置。
7 //
8 // 返回结果:
9 // 接收到的字节数。
10 //
11 // 异常:
12 // System.ArgumentNullException:
13 // buffer 为 null。
14 //
15 // System.Net.Sockets.SocketException:
16 // 试图访问套接字时发生错误。 有关更多信息,请参见备注部分。
17 //
18 // System.ObjectDisposedException:
19 // System.Net.Sockets.Socket 已关闭。
20 //
21 // System.Security.SecurityException:
22 // 调用堆栈中的调用方没有所需的权限。
23 public int Receive(byte[] buffer);

上面代码介绍了Receive方法接收参数及返回值。

1 private void ListenConn(object o)
2 {
3 //将参数o 转化为监听的socket
4 Socket socketListener = o as Socket;
5 //写入循环 每一个连接就创建一个通信用的socket
6 while (true)
7 {
8 //当有客户端连接成功 创建通信用的socket
9 Socket connSocket = socketListener.Accept();
10 string ip = connSocket.RemoteEndPoint.ToString();
11 ShowMsg(ip + " " + DateTime.Now.ToString() + " 连接成功");
12 //创建一个新线程去接收消息
13 Thread th = new Thread(ReceiveMsg);
14 th.Start(connSocket);
15
16 }
17
18 }

接收消息的代码:

1 //接收客户端的消息
2 private void ReceiveMsg(object o)
3 {
4 Socket connSocket = o as Socket;
5
6 //通信用的socket连接成功 就可以接收消息了
7 byte[] buffer = new byte[1024 * 1024 * 5];//5M缓存
8 while (true)
9 {
10 //count是当前接收的字节个数
11 int count = connSocket.Receive(buffer);
12 string ip = connSocket.RemoteEndPoint.ToString();
13 //判断接收到的字节个数 是0表示客户端关闭了
14 if (count > 0)
15 {
16
17 //将字节转换为字符串
18 string msg = Encoding.UTF8.GetString(buffer, 0, count);
19<
SVM分类与回归 - 侯凯  阅读原文»

SVM(支撑向量机模型)是二(多)分类问题中经常使用的方法,思想比较简单,但是具体实现与求解细节对工程人员来说比较复杂,如需了解SVM的入门知识和中级进阶可点此下载。本文从应用的角度出发,使用Libsvm函数库解决SVM模型的分类与回归问题。

说明:libsvm是实现svm的便捷开源工具,应用广泛,由国立台湾大学Chih-Chung Chang和Chih-Jen Lin编写,可以实现基于SVM的分类和回归。

1.分类

在Matlab下下载测试数据heart_sacle
运行程序:

load heart_scale;
train_data
= heart_scale_inst(1:150,:);
train_label
= heart_scale_label(1:150,:);
test_data
= heart_scale_inst(151:270,:);
test_label
= heart_scale_label(151:270,:);
train_data
=sparse(train_data);
test_data
=sparse(test_data);
libsvmwrite(
'traindata',train_label,train_data);
libsvmwrite(
'testdata',test_label,test_data);

这样得到的traindata和testdata中的数据结构和heart_scale_c相同。
训练部分:

[xlabel,xdata]=libsvmread('traindata');
xdata
=full(xdata);
model
=svmtrain(xlabel,xdata);%%具体参数可以参见svmtrain.c

返回模型的参数:
结构[Parameters, nr_class, totalSV, rho, Label, ProbA, ProbB, nSV, sv_coef, SVs]
model.Parameters参数意义从上到下依次为:
-s svm类型:SVM设置类型(默认0)
-t 核函数类型:核函数设置类型(默认2)
-d degree:核函数中的degree设置(针对多项式核函数)(默认3)
-g r(gama):核函数中的gamma函数设置(针对多项式/rbf/sigmoid核函数) (默认类别数目的倒数)
-r coef0:核函数中的coef0设置(针对多项式/sigmoid核函数)((默认0)
model.nr_class表示数据集中有多少类别;= 2 for regression/one-class svm
model.Label表示数据集中类别的标签都是什么
model.totalSV代表总共的支持向量的数目
model.nSV表示每类样本的支持向量的数目
model.ProbA和model.ProbB
使用-b参数时才能用到,用于概率估计。
-b probability_estimates: whether to train a SVC or SVR model for probability estimates,0 or 1 (default 0)
可以参见A note on Platt’s probabilistic outputs for support vector machines》论文
model.sv_coef是一个totalSV*1的矩阵,承装的是totalSV个支持向量在决策函数中的系数
model.SVs是一个totalSV×维度的稀疏矩阵,承装的是totalSV个支持向量
model.rho是决策函数中的常数项的相反数
测试部分:

[clabel,cdata]=libsvmread('testdata');
cdata
=full(cdata);
[predict_label, accuracy, dec_values]
= svmpredict(clabel, cdata, model);

返回参数:
predict_label是预测标签向量
accuracy从上到下依次的意义分别是:
-分类准率(分类问题中用到的参数指标)
-平均平方误差(MSE (mean squared error))[回归问题中用到的参数指标]
-平方相关系数(r2 (squared correlation coefficient))[回归问题中用到的参数指标]
dec_values是一个包含decision值或概率估计(-b 1)的矩阵,如果k个类,对于decision值,每行包含k(k-1)/2个二分类问题的结果;对于概率,每列包含k个属于每类的概率值
改变参数后:

model2=svmtrain(xlabel,xdata,'-c 1024 -g 0.001953125');
[predict_label2, accuracy2, dec_values2]
= svmpredict(clabel, cdata, model2);

model2
=svmtrain(xlabel,xdata,'-c 8 -g 0.03125 -b 1');
= svmpredict(clabel, cdata, model2, '-b 1');

附加注意事项
1.缩放训练和测试数据(上例Matlab数据已缩放)
应用SVM之前,缩放是非常重要的。缩放的最主要优点是能够避免大数值区间的属性过分支配了小数值区间的属性。另一个优点能避免计算过程中数值复杂度。因为关键值通常依赖特征向量的内积(inner products),例如,线性核和多项式核力,属性的大数值可能会导致数值问题。我们推荐将每个属性线性缩放到区间[-1,+1]或者[0, 1]。
当然,我们必须使用同样的方法缩放训练数据和测试数据。例如,假设我们把训练数据的第一个属性从[-10, +10]缩放到[-1, +1],那么如果测试数据的第一个属性属于区间[-11, +8],我们必须将测试数据转变成[-1.1, +0.8]。
svm-scale [options] data_filename
范围用-l, -u 指定,通常是[0,1],或是[-1,1]。(文本分类一般选[0,1])。
示例程序:训练集合测试集被分别缩放到[0,1]区间

$ ../svm-scale -l 0 -s range4 svmguide4 > svmguide4.scale
$ ..
/svm-scale -r range4 svmguide4.t > svmguide4.t.scale
$ python easy.py svmguide4.scale svmguide4.t.scale rem(libsvm中tools的程序)
Accuracy
= 89.4231% (279/312) (classification)

2.采用交叉验证选择最佳参数C与g(径向基核函数)
不同的参数(最常用的就是g和c)条件下会训练出不同的SVM,那怎么选取使SVM最好的参数呢,grid.py就是做这个的。
因此,这里要先用grid选取合适的C和g值。
Usage: grid.py [-log2c begin,end,step] [-log2g begin,end,step] [-v fold][-svmtrain pathname] [-gnuplot pathname] [-out pathname] [-png pathname][additional parameters for svm-train] dataset
一般log2c -10,10,1 ;log2g 10,-10,-1, -v 5即可
示例:

python grid.py -log2c -10,10,1 -log2g 10,-10,-1 trainset.scale

返回best-c和best-g,还同时还返回准确率。
3.上述Matlab操作在cmd命令窗口下也可完成,详见A Practical Guide to Support Vector Classi cation

2.回归

步骤:使用Libsvm中的Windows版本的工具svmscale.exe进行训练和测试数据的归一化,svmtrain.exe进行模型训练,svmpredict.exe进行预测
1.svmtrtrain.exe训练模型(归一化数据和分类问题类似)

svmtrain.exe -s 3 -p 0.0001 -t 2 -g 32 -c 0.53125 -n 0.99 feature.scaled

-s用来指定的SVM的类型(default 0)
0 – C-SVC
1 – nu-SVC
2 – one-class SVM
3 – epsilon-SVR
4 – nu-SVR
对于回归来说,只能选3或者4,3表示epsilon-support vector regression, 4表示nu-support vector regression。-t是选择核函数,通常选用RBF核函数,原因在“A Practical Guide support vector classification”中已经简单介绍过了。-p尽量选个比较小的数字。需要仔细调整的重要参数是-c和-g。除非用gridregression.py来搜索最优参数,否则只能自己慢慢试了。
用gridregression.py搜索最优参数的方法如下:

python.exe gridregression.py -svmtrain H:\SVM\libsvm-2.81\windows\svmtrain.exe -gnuplot C:\gp373w32\pgnuplot.exe -log2c -10,10,1 -log2g -10,10,1 -lo

阅读更多内容

没有评论:

发表评论