File size: 6,924 Bytes
b88c26d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/-
  SmoothLeakyActivation
  Smooth leaky activation function with bounded gradient properties
-/
import Mathlib
import Mathlib.Analysis.SpecialFunctions.Log.Basic
import Mathlib.Analysis.SpecialFunctions.Trigonometric.Basic
import Mathlib.Analysis.Calculus.Deriv.Basic

noncomputable section

open Real

-- ============================================================
-- Parameters
-- ============================================================

structure Params where
  alpha : ℝ
  beta : ℝ
  h_alpha_pos : 0 < alpha
  h_alpha_lt_one : alpha < 1
  h_beta_pos : 0 < beta

-- ============================================================
-- Activation Function
-- Standard smooth leaky ReLU: f(x) = (1+Ξ±)/2 * x + (1-Ξ±)/2 * (1/Ξ²) * log(cosh(Ξ²x))
-- Derivative: f'(x) = (1+α)/2 + (1-α)/2 * tanh(βx) ∈ (α, 1)
-- ============================================================

/-- The smooth leaky activation function -/
def f (p : Params) (x : ℝ) : ℝ :=
  (1 + p.alpha) / 2 * x + (1 - p.alpha) / 2 * (1 / p.beta) * Real.log (Real.cosh (p.beta * x))

/-- The derivative of the smooth leaky activation -/
def f' (p : Params) (x : ℝ) : ℝ :=
  (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * Real.tanh (p.beta * x)

-- ============================================================
-- Properties
-- ============================================================

/-- The gradient is always strictly positive -/
theorem deriv_pos (p : Params) : βˆ€ x : ℝ, f' p x > 0 := by
  intro x
  have h₁ : f' p x = (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * Real.tanh (p.beta * x) := rfl
  rw [h₁]
  have hβ‚‚ : Real.tanh (p.beta * x) > -1 := Real.neg_one_lt_tanh (p.beta * x)
  have hβ‚„ : 0 < p.alpha := p.h_alpha_pos
  have hβ‚… : p.alpha < 1 := p.h_alpha_lt_one
  have h₇ : 0 < 1 - p.alpha := by linarith
  have hβ‚ˆ : 0 < 1 + p.alpha := by linarith
  have h₁₀ : (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * Real.tanh (p.beta * x) β‰₯
      (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * (-1) := by
    have h₁₁ : Real.tanh (p.beta * x) β‰₯ -1 := by linarith
    nlinarith
  have h₁₁ : (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * (-1 : ℝ) = p.alpha := by ring
  linarith [p.h_alpha_pos]

/-- The gradient is bounded below 1 -/
theorem deriv_bounded (p : Params) : βˆ€ x : ℝ, f' p x < 1 := by
  intro x
  have h₁ : f' p x = (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * Real.tanh (p.beta * x) := rfl
  rw [h₁]
  have hβ‚‚ : Real.tanh (p.beta * x) < 1 := Real.tanh_lt_one (p.beta * x)
  have hβ‚… : p.alpha < 1 := p.h_alpha_lt_one
  have h₇ : 0 < 1 - p.alpha := by linarith
  have h₁₀ : (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * Real.tanh (p.beta * x) <
      (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * (1 : ℝ) := by nlinarith
  have h₁₁ : (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * (1 : ℝ) = 1 := by ring
  linarith

/-- As x β†’ +∞, f'(x) β†’ 1 -/
theorem deriv_limit_pos_inf (p : Params) :
    Filter.Tendsto (f' p) Filter.atTop (nhds 1) := by
  have htanh : Filter.Tendsto (fun x : ℝ => Real.tanh (p.beta * x)) Filter.atTop (nhds 1) := by
    have hbeta : Filter.Tendsto (fun x : ℝ => p.beta * x) Filter.atTop Filter.atTop :=
      Filter.Tendsto.atTop_mul_atTop (by linarith [p.h_beta_pos]) Filter.tendsto_id
    exact Real.tendsto_tanh_atTop.comp hbeta
  have : Filter.Tendsto (fun x : ℝ => (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * Real.tanh (p.beta * x))
      Filter.atTop (nhds ((1 + p.alpha) / 2 + (1 - p.alpha) / 2 * 1)) :=
    Filter.Tendsto.const_add _ (Filter.Tendsto.const_mul _ htanh)
  have heq : (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * 1 = 1 := by ring
  simp only [f']
  rwa [heq] at this

/-- As x β†’ -∞, f'(x) β†’ alpha -/
theorem deriv_limit_neg_inf (p : Params) :
    Filter.Tendsto (f' p) Filter.atBot (nhds p.alpha) := by
  have htanh : Filter.Tendsto (fun x : ℝ => Real.tanh (p.beta * x)) Filter.atBot (nhds (-1)) := by
    have hbeta : Filter.Tendsto (fun x : ℝ => p.beta * x) Filter.atBot Filter.atBot :=
      Filter.Tendsto.atBot_mul_atBot (by linarith [p.h_beta_pos]) Filter.tendsto_id
    exact Real.tendsto_tanh_atBot.comp hbeta
  have : Filter.Tendsto (fun x : ℝ => (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * Real.tanh (p.beta * x))
      Filter.atBot (nhds ((1 + p.alpha) / 2 + (1 - p.alpha) / 2 * (-1))) :=
    Filter.Tendsto.const_add _ (Filter.Tendsto.const_mul _ htanh)
  have heq : (1 + p.alpha) / 2 + (1 - p.alpha) / 2 * (-1) = p.alpha := by ring
  simp only [f']
  rwa [heq] at this

/-- f is C^∞ (infinitely differentiable) -/
theorem smooth (p : Params) : ContDiff ℝ ⊀ (f p) := by
  have h_lin : ContDiff ℝ ⊀ (fun x : ℝ => (1 + p.alpha) / 2 * x) :=
    (contDiff_const.mul contDiff_id)
  have h_cosh : ContDiff ℝ ⊀ (fun x : ℝ => Real.cosh (p.beta * x)) :=
    Real.contDiff_cosh.comp (contDiff_const.mul contDiff_id)
  have h_pos : βˆ€ x : ℝ, Real.cosh (p.beta * x) > 0 := fun x => Real.cosh_pos _
  have h_log : ContDiff ℝ ⊀ (fun x : ℝ => Real.log (Real.cosh (p.beta * x))) :=
    h_cosh.log (fun x => ne_of_gt (h_pos x))
  have h_scaled : ContDiff ℝ ⊀ (fun x : ℝ => (1 - p.alpha) / 2 * (1 / p.beta) * Real.log (Real.cosh (p.beta * x))) :=
    contDiff_const.mul h_log
  simp only [f]
  exact h_lin.add h_scaled

/-- f(x) < 0 for all x < 0 -/
theorem neg_range (p : Params) : βˆ€ x : ℝ, x < 0 β†’ f p x < 0 := by
  intro x hx
  simp only [f]
  have hβ‚„ : 0 < p.beta := p.h_beta_pos
  have hβ‚… : 0 < 1 + p.alpha := by linarith [p.h_alpha_pos]
  have h₆ : 0 < 1 - p.alpha := by linarith [p.h_alpha_lt_one]
  have h₇ : (0 : ℝ) < 1 / p.beta := by positivity
  have hβ‚ˆ : Real.log (Real.cosh (p.beta * x)) β‰₯ 0 :=
    Real.log_nonneg (Real.one_le_cosh _)
  have h₉ : (1 + p.alpha) / 2 * x < 0 := by nlinarith
  have h₁₂ : Real.log (Real.cosh (p.beta * x)) ≀ p.beta * |x| := by
    have hle : Real.cosh (p.beta * x) ≀ Real.exp (p.beta * |x|) := by
      calc Real.cosh (p.beta * x)
          ≀ Real.cosh (|p.beta * x|) := Real.cosh_abs _ β–Έ le_refl _
        _ = Real.cosh (p.beta * |x|) := by
            rw [abs_mul, abs_of_pos hβ‚„]
        _ ≀ Real.exp (p.beta * |x|) := Real.cosh_le_exp _
    linarith [Real.log_le_log (Real.cosh_pos _) hle,
              Real.log_exp (p.beta * |x|)]
  have h₁₃ : |x| = -x := abs_of_neg hx
  rw [h₁₃] at h₁₂
  have h₁₄ : (1 - p.alpha) / 2 * (1 / p.beta) * Real.log (Real.cosh (p.beta * x))
      ≀ (1 - p.alpha) / 2 * (-x) := by
    have : (1 - p.alpha) / 2 * (1 / p.beta) * (p.beta * (-x)) = (1 - p.alpha) / 2 * (-x) := by
      field_simp
    nlinarith
  have h₁₅ : (1 + p.alpha) / 2 * x + (1 - p.alpha) / 2 * (-x) = p.alpha * x := by ring
  linarith [mul_neg_of_pos_of_neg p.h_alpha_pos hx]

/-- f(0) = 0 -/
theorem f_zero (p : Params) : f p 0 = 0 := by
  simp [f, Real.cosh_zero, Real.log_one]

end