Skip to main content

fitting - Softmax Regression implementation


a[t_List,x_List]:=E^(t.Prepend[x,1])
hypothethis[t_List, k_, x_]:= Table[a[t[[j]], x], {j, 1, k-1}]/(1 +Sum[a[t[[j]],x],{j, 1, k-1}])

indicatorFunc[eqn_]:=If[eqn,1,0]

SoftmaxRegression[x_List, y_List]:=Module[{J, vars, b, k, n},
k = Length@Union[y];

n = Length[Transpose[x]]+1;
vars = Array[b, {k - 1, n}];
J[t_]:= (-1/Length[y])*(Sum[indicatorFunc[y[[i]] == k]*Log[1/(1 +Sum[a[t[[j]],x[[i]]],{j, 1, k-1}])]+Sum[indicatorFunc[y[[i]] ==j]*Log[a[t[[j]],x[[i]]]/(1 + Sum[a[t[[j]],x[[i]]],{j, 1, k-1}])],{j,1,k-1}],{i, 1,Length[y]}])+Sum[Sum[t[[i,j]]^2,{j, 1, n}],{i, 1, k-1}];
vars/.NMinimize[J[vars],Flatten@vars][[2]]
]

http://ufldl.stanford.edu/wiki/index.php/Softmax_Regression


I am trying to implement the softmax regression, which returns a list of coefficient for hypothethis function. And hypothethis function will gives the first n - 1 classes probability, which we can use to find the nth class's probability.


I used FisherIris data, in which there are 3 classes: virsicolor, verginica, setosa. I don't know why the 2nd class and the 3rd are combined somehow. There is something wrong in the implementation of my code but I don't know where is wrong.


iris = ExampleData[{"Statistics", "FisherIris"}];

rs = RandomSample[Range[150]];
n = Length[iris];
cut = Ceiling[0.8 n];
train = iris[[rs[[1 ;; cut]]]];
test = iris[[rs[[cut + 1 ;;]]]];
x = train[[All, 1 ;; 4]];
y = train[[All, -1]] /. {"setosa" -> 1, "versicolor" -> 2, "virginica" -> 3}

tList = SoftmaxRegression[x, y]


the result is:


 {{0.0268716, 0.0458991, 0.132301, -0.209938, -0.0960074}, {-0.00348727, -0.0128626, -0.0458174, 0.0371426, 0.00473217}}

p = hypothethis[tList, 3, #] & /@ test[[All, 1 ;; 4]]
{{0.218183, 0.390056}, {0.221959, 0.387587}, {0.251179,
0.367642}, {0.270846, 0.354952}, {0.452594, 0.249346}, {0.279229,
0.352813}, {0.220481, 0.385259}, {0.212727, 0.392914}, {0.433949,
0.25978}, {0.258379, 0.360879}, {0.264716, 0.362466}, {0.235144,
0.377701}, {0.450472, 0.249237}, {0.456505, 0.246573}, {0.199231,
0.401248}, {0.251868, 0.367067}, {0.194777, 0.399115}, {0.256978,

0.366888}, {0.200664, 0.399031}, {0.20611, 0.394495}, {0.190138,
0.407413}, {0.438089, 0.257827}, {0.450832, 0.249554}, {0.233257,
0.376698}, {0.247638, 0.372358}, {0.273605, 0.352006}, {0.208238,
0.392663}, {0.270954, 0.356693}, {0.202797, 0.394089}, {0.210708,
0.388326}}
AllClassProb[prob_List]:= Append[prob, 1 - Total[prob]]

probability = AllClassProb /@ p

We found the 3rd class's probability by the previous two.



{{0.218183, 0.390056, 0.391761}, {0.221959, 0.387587, 0.390454}, 
{0.251179, 0.367642, 0.381179}, {0.270846, 0.354952,
0.374202}, {0.452594, 0.249346, 0.29806}, {0.279229, 0.352813,
0.367959}, {0.220481, 0.385259, 0.39426}, {0.212727, 0.392914,
0.394358}, {0.433949, 0.25978, 0.306271}, {0.258379, 0.360879,
0.380741}, {0.264716, 0.362466, 0.372818}, {0.235144, 0.377701,
0.387155}, {0.450472, 0.249237, 0.300291}, {0.456505, 0.246573,
0.296921}, {0.199231, 0.401248, 0.399521}, {0.251868, 0.367067,
0.381066}, {0.194777, 0.399115, 0.406108}, {0.256978, 0.366888,
0.376134}, {0.200664, 0.399031, 0.400304}, {0.20611, 0.394495,

0.399395}, {0.190138, 0.407413, 0.402448}, {0.438089, 0.257827,
0.304084}, {0.450832, 0.249554, 0.299614}, {0.233257, 0.376698,
0.390045}, {0.247638, 0.372358, 0.380003}, {0.273605, 0.352006,
0.374389}, {0.208238, 0.392663, 0.399099}, {0.270954, 0.356693,
0.372353}, {0.202797, 0.394089, 0.403113}, {0.210708, 0.388326,
0.400966}}


augmentProb = MapThread[
Transpose[{#1, #2}] &, {Table[Range[Length[Transpose[probability]]], {Length[probability]}], probability}]


result = MaximalBy[#, Last] & /@ augmentProb

theoreticalResult = test /. {"setosa" -> 1, "versicolor" -> 2, "virginica" -> 3};
theoreticalResult[[All, -1]]
{3, 2, 2, 2, 1, 2, 3, 3, 1, 2, 2, 3, 1, 1, 3, 2, 3, 2, 3, 3, 3, 1, 1, 3, 2, 2, 3, 2, 3, 3}

exprimentalResult = Transpose[Flatten[result, 1]];
exprimentalResult[[1]]


{3, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 1, 2, 3, 3, 3, 3, 3, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3}


Comments

Popular posts from this blog

plotting - How to draw lines between specified dots on ListPlot?

I would like to create a plot where I have unconnected dots and some connected. So far, I have figured out how to draw the dots. My code is the following: ListPlot[{{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4,13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full] I have thought using ListLinePlot command, but I don't know how to specify to the command to draw only selected lines between the dots. Do have any suggestions/hints on how to do that? Thank you. Answer One possibility would be to use Epilog with Line : ListPlot[ {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {1, 4}, {2, 5}, {3, 6}, {4, 7}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {1, 10}, {2, 11}, {3, 12}, {4, 13}, {2.5, 7}}, Ticks -> {{1, 2, 3, 4}, None}, AxesStyle -> Thin, TicksStyle -> Directive[Black, Bold, 12], Mesh -> Full, Epilog -> { Line[ ...

list manipulation - Selecting multiple columns from a matrix?

Sample data: data = { {{2013, 1, 1}, 24.13, 167.67, 231.82}, {{2013, 1, 2}, 32.15, 170.92, 225.99}, {{2013, 1, 3}, 35.43, 172.68, 221.67}, {{2013, 1, 4}, 36.73, 173.05, 218.32}, {{2013, 1, 5}, 58.19, 165.96, 197.05}, {{2013, 1, 6}, 69.99, 163.50, 187.52}, {{2013, 1, 7}, 71.37, 154.21, 175.58}, {{2013, 1, 8}, 72.51, 149.66, 163.25}}; I want a DateListPlot with three graphs, so for a matrix formed by columns 1 and 2, one for columns 1 and 3, and 1 for columns 1 and 4. At the moment I'm using this code: data2 = Transpose[{data[[All, 1]], data[[All, 2]]}]; data3 = Transpose[{data[[All, 1]], data[[All, 3]]}]; data4 = Transpose[{data[[All, 1]], data[[All, 4]]}]; DateListPlot[{data2, data3, data4}, Joined -> True, Filling -> {3 -> {1}}] but I have a hunch that this can be done more efficiently. I don't like the Transpose s in particular. Any ideas? edit (for extra credit) What if I need to multiply the second column by 2, which in my solution is simp...

dynamic - How can I make a clickable ArrayPlot that returns input?

I would like to create a dynamic ArrayPlot so that the rectangles, when clicked, provide the input. Can I use ArrayPlot for this? Or is there something else I should have to use? Answer ArrayPlot is much more than just a simple array like Grid : it represents a ranged 2D dataset, and its visualization can be finetuned by options like DataReversed and DataRange . These features make it quite complicated to reproduce the same layout and order with Grid . Here I offer AnnotatedArrayPlot which comes in handy when your dataset is more than just a flat 2D array. The dynamic interface allows highlighting individual cells and possibly interacting with them. AnnotatedArrayPlot works the same way as ArrayPlot and accepts the same options plus Enabled , HighlightCoordinates , HighlightStyle and HighlightElementFunction . data = {{Missing["HasSomeMoreData"], GrayLevel[ 1], {RGBColor[0, 1, 1], RGBColor[0, 0, 1], GrayLevel[1]}, RGBColor[0, 1, 0]}, {GrayLevel[0], GrayLevel...