3
$\begingroup$

I have a Manipulate-based figure in which I'd like to place a compact legend in the upper left corner (within the figure's frame). But by default, the items in the legend are spaced too far apart, and have a font that's too big (and different from the font used for the axes and other labels):

enter image description here

How do I control the spacing and font size for my plot legend? I've tried all the answers I've found here that seem relevant, but I fear that even if I hit on the potentially right one, it isn't clear where to apply the solution in the context of my code.

Ideally, I'd like a solution that simplifies the code as a whole, or at least doesn't make it more complex. I've long passed the point I often reach in Mathematica where I think: "I should have just done this in Python!"


sigmoid[z_]:= E^z/(E^z+1)
relu[z_]:=Max[{0, #}]&/@z
softplus[z_]:=Log[1+E^z]

Manipulate[
total=E^rng/saturation;
Show[{
        Plot[{E^z/total},  {z, -rng, Log[saturation*total](*==rng*)},  PlotRange->{{-rng, rng},  {0, prng}}, 
            PlotLegends->Placed[{StringForm["Softmax (`1`%)", NumberForm[saturation*100, {3, 1}]]}, {Left, Top}], PlotStyle->Blue, 
            Epilog->{Text[Style[N[E^rng/total, 4]], {rng+.3,  E^rng/total}, {-0.5, 0}]}], 
        Plot[{sigmoid@z},  {z, -rng, rng},  PlotRange->{{-rng, rng},  {0, prng}}, 
            PlotLegends->Placed[{"Sigmoid"}, {Left, Top}],  PlotStyle->Orange], 
        Plot[{relu@z}, {z, -rng, rng}, PlotRange->{{-rng, rng},  {0, prng}}, 
            PlotLegends->Placed[{"ReLU"}, {Left, Top}], PlotStyle->Purple], 
        Plot[{softplus@z}, {z, -rng, rng}, PlotRange->{{-rng, rng},  {0, prng}}, 
            PlotLegends->Placed[{"Softplus"}, {Left, Top}], PlotStyle->Green]
    }, FrameLabel->{"z", "a(z)"}, AxesOrigin->{-rng, 0}, Frame->True, 
    Prolog->{GrayLevel[.95], Line[{{0, 0}, {0, prng}}],  Dashed,  Line[{{-rng, 1.0}, {rng, 1.0}}]}, 
    PlotRangeClipping->False, ImagePadding->{{Automatic, 45}, {Automatic, Automatic}}], 
    {{rng, 5,  "Logit (z) range"}, 1, 10}, 
    {{saturation,  1, "Logit concentration"}, 1, 1/n, 0.001}, (* Activation,  a(z),  fraction in highest *)
    Delimiter, 
    {{n, 10, "Classes (has no effect)"}, 1, 50, 1,  Visible->False}, 
    {{prng, 1.1, "Activation (a) scale range"}, 1.0, 2*rng}]
$\endgroup$
3
  • $\begingroup$ How about replacing your PlotLegends with something like this Placed[LineLegend[{Red}, {Style["Softplus", FontSize -> 10]}, LegendMargins -> 0], {Left, Top}]? $\endgroup$
    – swish
    Aug 16, 2017 at 20:55
  • $\begingroup$ Why do you use Show on 4 separate plots instead of just using one Plot with 4 separate functions? $\endgroup$
    – Carl Woll
    Aug 16, 2017 at 21:01
  • $\begingroup$ @CarlWoll: See my comment to kglr's answer. $\endgroup$
    – orome
    Aug 16, 2017 at 21:56

2 Answers 2

4
$\begingroup$
sigmoid[z_] := E^z/(E^z + 1)
relu[z_] := Max[{0, #}] & /@ z
softplus[z_] := Log[1 + E^z]

Manipulate[total = E^rng/saturation;
 Plot[{ConditionalExpression[E^z/total, -rng <= z <= Log[saturation total]], 
   sigmoid@z, relu@z, softplus@z}, {z, -rng, rng}, 
  PlotRange -> {{-rng, rng}, {0, prng}}, AxesOrigin -> {-rng, 0}, 
  Frame -> True, PlotStyle -> {Blue, Orange, Purple, Green}, ImageSize -> 500, 
  PlotRangeClipping -> False, PlotRangePadding -> Automatic, 
  ImagePadding -> {{Automatic, 45}, {Automatic, Automatic}}, 
  Epilog -> {Text[Style[N[E^rng/total, 4]], {rng + .3, E^rng/total}, {-0.5, 0}], 
    GrayLevel[.9], Line[{{0, 0}, {0, prng}}], Dashed, 
    Line[{{-rng, 1.0}, {rng, 1.0}}]}, FrameLabel -> {"z", "a(z)"}, 
  PlotLegends -> Placed[LineLegend[Automatic, 
    {StringForm["Softmax (`1`%)", NumberForm[saturation*100, {3, 1}]], 
    "Sigmoid", "ReLU", "Softplus"}, 
  "Spacings" -> {.5, .1}, LabelStyle -> 16], {Left, Top}]], 
 {{rng, 5, "Logit (z) range"}, 1, 10}, 
 {{saturation, 1, "Logit concentration"}, 1, 1/n, 0.001}, 
 Delimiter, 
 {{n, 10, "Classes (has no effect)"}, 1, 50, 1, Visible -> False},
 {{prng, 1.1, "Activation (a) scale range"}, 1.0, 2*rng}]

enter image description here

Note: You can use LegendLayout -> (Grid[##, Spacings -> {.5, .1}, Alignment -> Left] &) instead of "Spacings" -> {.5,.1} on macOS to avoid red syntax highlighting.

$\endgroup$
8
  • $\begingroup$ Nice solution. I hadn't thought of that approach to achieving a different domain for the softmax function (actually, it doesn't need to be different, as you'll see if you substitute total and solve, but it's still good to know that trick. I'll need to study how you managed to get the text on the outside of the graph using this method (one Plot): that didn't work for me earlier when I first tried it (many times). $\endgroup$
    – orome
    Aug 16, 2017 at 21:56
  • 1
    $\begingroup$ @raxa, I didn't make any changes in your code to get the text outside the graph. Your Epilog and ImagePadding settings places the text in the right place. $\endgroup$
    – kglr
    Aug 16, 2017 at 23:07
  • $\begingroup$ I had to put things into several Plots for it to work before. No idea why! $\endgroup$
    – orome
    Aug 16, 2017 at 23:10
  • $\begingroup$ Confirming that this works. But (FWIW) I just don't understand why I need to create a low level Placed@LineLegend to accomplish what should be a basic part of any legend: spacing and font size. Also that red quoted "Spacings" option worries me. Is there nothing more reliable? $\endgroup$
    – orome
    Aug 17, 2017 at 15:16
  • $\begingroup$ @raxa, you can control the font sizes by wrapping labels with Style[#, 16] without having to use LineLegend[...] (i.e., PlotLegends -> Placed[Style[#, 16] & /@ {StringForm["Softmax (1%)", NumberForm[saturation*100, {3, 1}]], "Sigmoid", "ReLU", "Softplus"}, {Left, Top}] works). However, i don't know a more convenient way to control spacings. Btw, I don't get red highlighting for "Spacings" in version 9 and version 11. $\endgroup$
    – kglr
    Aug 17, 2017 at 21:58
3
$\begingroup$

you can specify the position and other options of the elements in PlotLegends. you can read the rules in the legends placement section here http://reference.wolfram.com/language/ref/PlotLegends.html

here is an example of your code with fonts ,color,position and spacing modified. I was not able to avoid the "{ }" around the text though, maybe someone else will tell explain it to us

sigmoid[z_] := E^z/(E^z + 1)
relu[z_] := Max[{0, #}] & /@ z
softplus[z_] := Log[1 + E^z]

Manipulate[total = E^rng/saturation;
 Show[{Plot[{E^z/total}, {z, -rng, 
     Log[saturation*total](*\[Equal]rng*)}, 
    PlotRange -> {{-rng, rng}, {0, prng}}, 
    PlotLegends -> 
     Placed[{Text[
        Style[StringForm["Softmax (`1`%)", 
          NumberForm[saturation*100, {3, 1}]], Blue, 7]]}, {{0.11, 
        0}, {0, -5.6}}], PlotStyle -> Blue, 
    Epilog -> {Text[
       Style[N[E^rng/total, 4]], {rng + .3, E^rng/total}, {-0.5, 
        0}]}], Plot[{sigmoid@z}, {z, -rng, rng}, 
    PlotRange -> {{-rng, rng}, {0, prng}}, 
    PlotLegends -> 
     Placed[{Text[Style[{"Sigmoid"}, Italic, Orange, 7]]}, {{0.11, 
        0}, {0, -5.2}}], PlotStyle -> Orange], 
   Plot[{relu@z}, {z, -rng, rng}, 
    PlotRange -> {{-rng, rng}, {0, prng}}, 
    PlotLegends -> 
     Placed[{Text[Style[{"Relu"}, Italic, Purple, 7]]}, {{0.11, 
        0}, {0, -5}}], PlotStyle -> Purple], 
   Plot[{softplus@z}, {z, -rng, rng}, 
    PlotRange -> {{-rng, rng}, {0, prng}}, 
    PlotLegends -> 
     Placed[{Text[Style[{"SoftPlus"}, Italic, Red, 7]]} , {{0.11, 
        0}, {0, -4.7}}], PlotStyle -> Green]}, 
  FrameLabel -> {"z", "a(z)"}, AxesOrigin -> {-rng, 0}, Frame -> True,
   Prolog -> {GrayLevel[.95], Line[{{0, 0}, {0, prng}}], Dashed, 
    Line[{{-rng, 1.0}, {rng, 1.0}}]}, PlotRangeClipping -> False, 
  ImagePadding -> {{Automatic, 45}, {Automatic, Automatic}}], {{rng, 
   5, "Logit (z) range"}, 1, 
  10}, {{saturation, 1, "Logit concentration"}, 1, 1/n, 
  0.001},(*Activation,a(z),fraction in highest*)Delimiter, {{n, 10, 
   "Classes (has no effect)"}, 1, 50, 1, 
  Visible -> False}, {{prng, 1.1, "Activation (a) scale range"}, 1.0, 
  2*rng}]

enter image description here

$\endgroup$
1
  • 1
    $\begingroup$ Great job! To reduce the verbosity the Text wrapper around Style in the PlotLegends -> Placed[... expressions is not required. Works fine with only Style. $\endgroup$ Aug 16, 2017 at 22:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.