数理社会学:なぜ社会は狭いのか?

ネットワークの作成方法の例と距離の測りかた
Regular Networks, Small-World Networks

mkRegG=function(n_node,n_edge){
# input
# n_node: number of nodes
# n_edge: number of edges / 2  
  M=matrix(0,n_node,n_node) 
  for (i_loop in 1:n_edge){
    M=M+diag(1,n_node,n_node)[, c((i_loop+1):n_node,1:i_loop)]
  }
  return(M+t(M))
}

# small-world network
G=mkRegG(100,2);
n_node=ncol(G);
prob=0.05;
for (i_node in 1:n_node) {
  node=G[i_node,]
  linked=which(node==1) 
  woLinked=which(node==0) 
  woLinked=woLinked[woLinked!=i_node]
  rwVec=linked[which(runif(length(linked)) < prob)]
  nRW=length(rwVec)
  if (nRW>0) {
    newLink=sample(woLinked,nRW)
    G[i_node,newLink]=1;G[newLink,i_node]=1
    G[i_node,rwVec]=0;G[rwVec,i_node]=0
  }
}  

# cal. shortest path
dijkstra2<-function(G,nodeID){
n_node=nrow(G)
G[which(G==0)]=Inf;diag(G)=0
d=rep(Inf,n_node);d[nodeID]=0
M=1:n_node;M=M[-nodeID]
while(length(M)>0) {
  for (j in 1:n_node) 
    {
      d[j]=min(d[j],d[nodeID]+G[nodeID,j])
    }
    nodeID=M[which(d[M]==min(d[M]))]
    n_remove=length(nodeID)
    for (i_remove in 1:n_remove){
      M=M[-which(M==nodeID[i_remove])]
    }
  }
 return(d)
}

昔のバージョン(多分)

# regular network 
mkRegG=function(n_node,n_edge){
# input
# n_node: number of nodes
# n_edge: number of edges / 2  
  M=matrix(0,n_node,n_node)	
  for (i_loop in 1:n_edge){
    M=M+diag(1,n_node,n_node)[, c((i_loop+1):n_node,1:i_loop)]
  }
  return(M+t(M))
}
# WS model (small-world)
mkWSG=function(regG,prob){
# input
# regG: regular network
# prob: probability of rewiring / 2
n_node=ncol(regG)
M=regG;
  for (i_node in 1:n_node){
    edge=which(M[i_node,]==1)
    rwVec=edge[which(runif(length(edge)) < prob)]
    nRW=length(rwVec);
    if (nRW>0) {
      newEdge=sample(seq(n_node)[-i_node],nRW);
      while (any(M[i_node,newEdge]==1) & any(M[i_node,rwVec]==1)){
        newEdge=sample(seq(n_node)[-i_node],nRW);
    }
    M[i_node,newEdge]=1;M[newEdge,i_node]=1;
    M[i_node,rwVec]=0;M[rwVec,i_node]=0;	
    }
  }
  return(M);
}
# scale-free network
mkFSG=function(n_node,n_edge) {
# input
# n_node: number of nodes
# n_edge: minimum number of edges
  M=matrix(1,n_edge+1,n_edge+1)-diag(n_edge+1)
  for (i_node in (n_edge+2):n_node) {
    Pnode=rowSums(M)/sum(M)	
    cumPnode=c(0,cumsum(Pnode))
    vec=matrix(0,1,i_node-1)
      while (sum(vec) < n_edge) {
        vec[max(which(cumPnode<=runif(1)))]=1
      }
    M=rbind(M,vec);
    M=cbind(M,c(vec,0));
  }
  return(M)
}

認知情報解析 デマの拡散モデル

Dema_WO_cr<-function(N,ps,ave.followers,n_rep){
  # N - numbers of S, Ig, Is
  # ps - probs for S->I, Ig->I
  dt=0.01;ts=seq(1,n_rep,dt);n_ts=length(ts);
  S=matrix(0,nrow=n_ts,ncol=1);S[1]=N[1];
  Ig=matrix(0,nrow=n_ts,ncol=1);Ig[1]=N[2];
  I=matrix(0,nrow=n_ts,ncol=1);I[1]=N[3];
  N=S[1]+Ig[1]+I[1];
  F=ave.followers;
  p.S2I=ps[1];p.Ig2I=ps[2]

  # main 
  for (i_time in 1:(n_ts-1)) {
    S[i_time+1]=S[i_time]-F/N*I[i_time]*S[i_time]*dt
    Ig[i_time+1]=Ig[i_time]+((1-p.S2I)*F/N*I[i_time]*S[i_time]-p.Ig2I*F/N*Ig[i_time]*I[i_time])*dt
    I[i_time+1]=I[i_time]+(p.S2I*F/N*I[i_time]*S[i_time]+p.Ig2I*F/N*Ig[i_time]*I[i_time])*dt
  }
  # plotting results
  plot(ts,S,type="l",lwd=4,col="red", main="Distribution of rumors in Twitter "
    ,xlab="time", ylab="Proportions of People",cex.lab=1.3,ylim=c(0,S[1]))
  lines(ts,Ig,type="l",lwd=4,col="blue")
  lines(ts,I,type="l",lwd=4,col="green")
  legend("right", c("Not seen rumors nor corrections","Seen rumors", "tweeted rumours"), 
  col=c("red","blue","green"),lty=rep(1,3),lwd=4)
}

Dema_W_cr<-function(N,ps,ave.followers,n_rep){
  # N - numbers of S, Ig, Is
  # ps - probs for S->I, Ig->I
  dt=0.01;ts=seq(1,n_rep,dt);n_ts=length(ts);
  S=matrix(0,nrow=n_ts,ncol=1);S[1]=N[1];
  Ig=matrix(0,nrow=n_ts,ncol=1);Ig[1]=N[2];
  I=matrix(0,nrow=n_ts,ncol=1);I[1]=N[3];
  Rg=matrix(0,nrow=n_ts,ncol=1);Rg[1]=N[4];
  R=matrix(0,nrow=n_ts,ncol=1);R[1]=N[5];
  N=S[1]+Ig[1]+I[1]+Rg[1]+R[1];
  F=ave.followers;
  p.S2I=ps[1];p.Ig2I=ps[2];p.S2R=ps[3];p.Ig2R=ps[4];p.I2R=ps[5];p.Rg2R=ps[6];

  # main 
  for (i_time in 1:(n_ts-1)) {
    S[i_time+1]=S[i_time]+(-F/N*I[i_time]*S[i_time]-F/N*R[i_time]*S[i_time])*dt
    Ig[i_time+1]=Ig[i_time]+((1-p.S2I)*F/N*I[i_time]*S[i_time]-p.Ig2I*F/N*Ig[i_time]*I[i_time]
      -F/N*Ig[i_time]*R[i_time])*dt
    I[i_time+1]=I[i_time]+(p.S2I*F/N*I[i_time]*S[i_time]+p.Ig2I*F/N*Ig[i_time]*I[i_time]
      -F/N*I[i_time]*R[i_time])*dt
    Rg[i_time+1]=Rg[i_time]+((1-p.S2R)*F/N*R[i_time]*S[i_time]+(1-p.Ig2R)*F/N*Ig[i_time]*R[i_time]
      +(1-p.I2R)*F/N*I[i_time]*R[i_time]-p.Rg2R*F/N*Rg[i_time]*R[i_time])*dt
    R[i_time+1]=R[i_time]+(p.S2R*F/N*R[i_time]*S[i_time]+p.Ig2R*F/N*Ig[i_time]*R[i_time]
      +p.I2R*F/N*I[i_time]*R[i_time]+p.Rg2R*F/N*Rg[i_time]*R[i_time])*dt
  }
  # plotting results
  plot(ts,S,type="l",lwd=4,col="red", main="Distribution of rumors in Twitter "
    ,xlab="time", ylab="Proportions of People",cex.lab=1.3,ylim=c(0,S[1]*1.25))
  lines(ts,Ig,type="l",lwd=4,col="blue")
  lines(ts,I,type="l",lwd=4,col="green")
  lines(ts,Rg,type="l",lwd=4,col="magenta")
  lines(ts,R,type="l",lwd=4,col="cyan")
  legend("topright", c("Not seen rumors nor corrections","Seen rumors", "tweeted rumours",
    "Seen corrections","tweeted corrections"), 
  col=c("red","blue","green","magenta","cyan"),lty=rep(1,5),lwd=4)
  return(data.frame(S,Ig,I,Rg,R))
}

w=Dema_W_cr(c(10000,0,100,0,1),c(0.001,0.01,0.01,0.01,0.01,0.01),20,50)

twitterDema

evo game – fairness

10切れのケーキを2人で分け合うゲーム
戦略は0~10個を相手に要求するといった11種類。
利得は2人の要求数の和が10以下の場合、要求した数だけで、そうでない場合は0。

cakeG

# a simple implementation
N_game=50;N_slice=10;
PropDemand=runif(N_slice+1);
PropDemand=PropDemand/sum(PropDemand);
PayMat=rbind(c(rep(0,11)),c(rep(1,10),0),c(rep(2,9),0,0),c(rep(3,8),0,0,0),
 c(rep(4,7),rep(0,4)),c(rep(5,6),rep(0,5)),c(rep(6,5),rep(0,6)),c(rep(7,4),rep(0,7)),
 c(rep(8,3),rep(0,8)),c(rep(9,2),rep(0,9)),c(rep(10,1),rep(0,10)))
histPD=matrix(0,nrow=N_game,ncol=N_slice+1);
histPD[1,]=PropDemand;
for (i_gen in 2:N_game) {
  PD2=matrix(PropDemand,nrow=N_slice+1,ncol=N_slice+1,byrow=T)
  Ws=rowSums(PD2*PayMat);
  meanW=sum(outer(PropDemand,PropDemand)*PayMat);
  PropDemand=PropDemand*(Ws/meanW)
  histPD[i_gen,]=PropDemand;
}
cols=c("black","red","cyan","green","blue","magenta","pink","brown","gray","orange","black")
plot(histPD[,1],xlim=c(1,N_game),ylim=c(0,1),type='l',col='black');
for (i_slice in 2:(N_slice+1)) {
  lines(histPD[,i_slice],type='l',col=cols[i_slice])
}

# in a form of differential equations
PropDemand=runif(N_slice+1);
PropDemand=PropDemand/sum(PropDemand);
tStep=0.01;ts=seq(0,30,tStep);Nts=length(ts)
histPD=matrix(0,nrow=Nts,ncol=N_slice+1);
histPD[1,]=PropDemand;
for (i_gen in 2:Nts) {
  PD2=matrix(PropDemand,nrow=N_slice+1,ncol=N_slice+1,byrow=T)
  Ws=rowSums(PD2*PayMat);
  meanW=sum(outer(PropDemand,PropDemand)*PayMat);
  PropDemand=PropDemand+PropDemand*((Ws-meanW)/meanW)*tStep
  histPD[i_gen,]=PropDemand;
}
cols=c("black","red","cyan","green","blue","magenta","pink","brown","gray","orange","black")
plot(histPD[,1],xlim=c(1,Nts),ylim=c(0,1),type='l',col='black',lwd=3);
for (i_slice in 2:(N_slice+1)) {
  lines(histPD[,i_slice],type='l',col=cols[i_slice],lwd=3)
}

数理社会学:軍拡モデル

軍拡モデル
2国間の軍事拡大モデル

### 設定
# parameters
a: X国の自国の戦力・軍事に対する抑制率
k: Y国に戦力に対するX国の戦力の増加率
g: X国の定常的な軍事費(戦力の増加量)
b: Y国の自国の戦力・軍事に対する抑制率
l: X国に戦力に対するY国の戦力の増加率
h: Y国の定常的な軍事費(戦力の増加量)
# 戦力の推移設定
X国:dx/dt=-ax+ky+g
y国:dy/dt=lx-by+h
# 引数:
a,b,k,l,g,h (上記)
dt 時間の推移

mil_exp<-function(a,b,k,l,g,h,dt) {
  timeSep=dt;ts=seq(1,50,timeSep);n_ts=length(ts)
  x=matrix(0,nrow=n_ts,ncol=1);y=matrix(0,nrow=n_ts,,ncol=1)
  initX=c(rep(-40,5),rep(-20,5),rep(0,5),rep(20,5),rep(40,5))
  initY=c(rep(c(-40,-20,0,20,40),5))
  initX=initX[-13];initY=initY[-13]
  lengthINI=length(initX)
  for (i_ini in 1:lengthINI) {  
    x[1]=initX[i_ini];y[1]=initY[i_ini];
    for (i_gen in 2:n_ts) {
       x[i_gen]=x[i_gen-1]+(-a*x[i_gen-1]+k*y[i_gen-1]+g)*timeSep
       y[i_gen]=y[i_gen-1]+(l*x[i_gen-1]-b*y[i_gen-1]+h)*timeSep
    }  
    if (i_ini==1) {  
       plot(x,y,xlim=c(-40,40),ylim=c(-40,40),col=4,type='l',lwd=2,
         xlab="Nation X's Military Force",ylab="Nation X's Military Force")
       arrows(x[2],y[2],x[3],y[3],col=4,lwd=2,length=0.15)
  } else {  
       lines(x, y, col=4, lwd=2)
       arrows(x[2], y[2], x[3], y[3], col=4,lwd=2, length=0.15)
    }  
  }  
}  
mil_exp(1,2,0.5,0.1,10,10,0.05)

mil_exp

認知情報解析 Jo Project beta 2

// openCVを使った顔検出
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv/highgui.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv/cv.h"
#include "iostream"
#include "stdlib.h"
#include "fstream"

using namespace cv;
int main(int argc, char **argv) {
  IplImage *src_img=0, *src_gray=0;
  if (argc < 2 || (src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR)) == 0)
    return -1;
  src_gray = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 1);
    
  CvMemStorage *storage = 0;
  storage = cvCreateMemStorage (0);
  cvClearMemStorage (storage);
  cvCvtColor (src_img, src_gray, CV_BGR2GRAY);
  cvEqualizeHist (src_gray, src_gray);
    
  CvMemStorage* FaceStorage = cvCreateMemStorage(0);
  CvHaarClassifierCascade* FaceCascade = (CvHaarClassifierCascade*)
    cvLoad("/opt/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt_tree.xml");
    
  std::ofstream out_file("DetectedFace.out");
  out_file<<"xMin,"<<"yMin,"<<"xMax,"<<"yMax"<<'\n';

  cvClearMemStorage( FaceStorage );
  CvSeq* FaceObjects = cvHaarDetectObjects(src_img,FaceCascade,FaceStorage,1.1,4,0,
    cvSize( 30, 30 ));
  CvRect* rF;
  // detect at most 10 faces
  int n=std::min(10,(FaceObjects ? FaceObjects->total : 0 ));
  for (int i=0;i<n;++i){
    rF = ( CvRect* )cvGetSeqElem( FaceObjects, i );
    out_file<<rF->x<<","<< rF->y<<","<<rF->x+rF->width<<","<<rF->y+rF->height<<'\n';
  }
  cvReleaseImage(&src_img);
  cvReleaseImage(&src_gray); 
  return 0;
}
# 上のopenCVのプログラムをRで使用する関数
JoFaceDetection<-function(file_name) {
  res<-system(paste("./JoFaceDetect ",file_name))
  if (res!=0) {
    warning("incorrect file name");
    return(-99)   	
  } else {
    xys=read.csv("DetectedFace.out");
    if (nrow(xys)!=0) {
      print("successfully detected face(s)");
      return(xys);
    } else {
      print("no face was detected");
      return(-99);
    }
  }
}

実行例

loc<-JoFaceDetection("~/Downloads/IMG_2095.jpg")
[1] "successfully detected face(s)"
> loc
  xMin yMin xMax yMax
1  307  114  521  328

認知情報解析B face detection

徐くんプロジェクト
OpenCVを使った顔と目の検出。

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv/highgui.h"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

int main(int argc, char** argv){
  IplImage* img=cvLoadImage(argv[1]);
  CvMemStorage* FaceStorage = cvCreateMemStorage(0);
  CvMemStorage* EyeStorage = cvCreateMemStorage(0);
  CvHaarClassifierCascade* FaceCascade = (CvHaarClassifierCascade*)  
   cvLoad("/opt/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt_tree.xml");
  CvHaarClassifierCascade* EyeCascade =(CvHaarClassifierCascade*) 
   cvLoad("/opt/local/share/OpenCV/haarcascades/haarcascade_eye_tree_eyeglasses.xml");
  double scale = 1.2;
  
  // Detect Faces
  cvClearMemStorage(FaceStorage);
  CvSeq* FaceObjects = cvHaarDetectObjects(img,FaceCascade,FaceStorage,scale,1.1,0,cvSize(1,1));
  CvRect* rF;
  // Loop through objects and draw boxes
  for (int i=0;i<(FaceObjects ? FaceObjects->total:0);i++ ){
    rF = ( CvRect* )cvGetSeqElem(FaceObjects,i);
    cvRectangle(img,cvPoint(rF->x,rF->y),cvPoint(rF->x+rF->width,rF->y+rF->height ),
      CV_RGB(255,0,0),3,4,0);
  }
  // Detect Eyes
  cvClearMemStorage(EyeStorage);
  CvSeq* EyeObjects = cvHaarDetectObjects(img,EyeCascade,EyeStorage,scale,1.1,0,cvSize(1,1));
  CvRect* rE;
  // Loop through objects and draw boxes
  for (int i=0;i<(EyeObjects ? EyeObjects->total:0);i++){
    rE = ( CvRect* )cvGetSeqElem(EyeObjects,i);
    cvRectangle(img,cvPoint(rE->x,rE->y),cvPoint(rE->x+rE->width,rE->y+rE->height ),
      CV_RGB(0,0,255),3,4,0);
  }
  // Displaying image
  cvNamedWindow("Face&Eye Detection");
  cvShowImage("Face&Eye Detection",img);
  cvWaitKey();
  cvReleaseImage(&img);    
  return 0;
}

opencvFD01input.jpg opencvFD01output.jpg

パラメターを変えないと、うまくは検出されないこともある。口と鼻の検出の精度は低いみたい。

single layer perceptron

勾配法と確率的最適化による学習例:

# 2変数からなる16種類のロジック
x=matrix(c(1,1,1,1,1,0,1,0,1,1,0,0),ncol=4);
y=matrix(c(0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,0,0,1,1,0,1,0,1,1,0,0,1,0,
  1,1,0,1,0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1),byrow=T,ncol=4)

> x # input matrix
     [,1] [,2] [,3] [,4]
[1,]    1    1    1    1   # X0
[2,]    1    1    0    0   # X1
[3,]    1    0    1    0   # X2
> y
      [,1] [,2] [,3] [,4]
 [1,]    0    0    0    0  # none
 [2,]    0    0    0    1  # notX1 & notX2
 [3,]    0    0    1    0  # notX1 & X2
 [4,]    0    1    0    0  # X1 & notX2
 [5,]    1    0    0    0  # X1 & X2
 [6,]    0    0    1    1  # notX1
 [7,]    0    1    0    1  # notX2
 [8,]    1    0    0    1  # {X1 & X2} or {notX1 & notX2}
 [9,]    0    1    1    0  # {X1 & notX2} or {notX1 & X2}
[10,]    1    0    1    0  # X2
[11,]    1    1    0    0  # X1
[12,]    1    1    1    0  # X1 or X2
[13,]    1    1    0    1  # X1 or notX2
[14,]    1    0    1    1  # notX1 or X2
[15,]    0    1    1    1  # notX1 or notX2
[16,]    1    1    1    1  # all

# 勾配法
stepSize=0.1;gamma=5;logicID=2;
w=matrix(rnorm(3),nrow=1);
for (i_tr in 1:2000) {
  for (i_inst in 1:4){
    a=w%*%x[,i_inst,drop=F]
    s=1/(1+exp(-gamma*a))
    w=w+stepSize*(y[logicID,i_inst]-s)*s*(1-s)*gamma*x[,i_inst]
  }
}
for (i_inst in 1:4){
  a=w%*%x[,i_inst,drop=F]
  print(1/(1+exp(-gamma*a)))
}

# 確率的最適化法(焼きなまし法)
gamma=2;logicID=2;
w=matrix(rnorm(3),nrow=1);
err=4;width=1;sTemp=matrix(0,nrow=1,ncol=3);C=0.25
for (i_tr in 1:5000) {
  wTemp=w+rnorm(3,mean=0,sd=width)
  for (i_inst in 1:4) {
    a=wTemp%*%x[,i_inst,drop=F]
    sTemp[i_inst]=1/(1+exp(-gamma*a))
  }
  errTemp=sum((sTemp-y[logicID,])^2)
  delta=errTemp-err;
  prob=1/(1+exp(delta/(C*width)))
  if (runif(1) <  prob) {
    w=wTemp
    err=errTemp
  }
  width=width*0.99
}
for (i_inst in 1:4) {
  a=w%*%x[,i_inst,drop=F]
  print(1/(1+exp(-gamma*a)))
}