Exemplo n.º 1
0
    def __compute_error_debug(self, p, x):
        """Compute the error function using the current parameter values (debug version)."""

        # Fetch the number of training points.
        n = len(x)

        # Unpack the network parameters.
        H = len(self.v)
        (w, u, v) = np.hsplit(p, 3)

        # Compute the forward pass through the network.
        z = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                z[i, k] = x[i]*w[k] + u[k]
        s = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                s[i, k] = sigma.s(z[i, k])
        s1 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                s1[i, k] = sigma.s1(s[i, k])
        s2 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                s2[i, k] = sigma.s2(s[i, k])
        N = np.zeros(n)
        for i in range(n):
            for k in range(H):
                N[i] += v[k]*s[i, k]
        dN_dx = np.zeros(n)
        for i in range(n):
            for k in range(H):
                dN_dx[i] += s1[i, k]*v[k]*w[k]
        d2N_dx2 = np.zeros(n)
        for i in range(n):
            for k in range(H):
                d2N_dx2[i] += v[k]*s2[i, k]*w[k]**2
        Yt = np.zeros(n)
        for i in range(n):
            Yt[i] = self.__Ytf(x[i], N[i])
        dYt_dx = np.zeros(n)
        for i in range(n):
            dYt_dx[i] = self.__dYt_dxf(x[i], N[i], dN_dx[i])
        d2Yt_dx2 = np.zeros(n)
        for i in range(n):
            d2Yt_dx2[i] = self.__d2Yt_dx2f(x[i], N[i], dN_dx[i], d2N_dx2[i])
        G = np.zeros(n)
        for i in range(n):
            G[i] = self.eq.Gf(x[i], Yt[i], dYt_dx[i], d2Yt_dx2[i])
        E = 0
        for i in range(n):
            E += G[i]**2

        return E
Exemplo n.º 2
0
    def run_derivative2_debug(self, x):
        """Compute the trained 2nd derivative (debug version)."""
        n = len(x)
        H = len(self.v)
        w = self.w
        u = self.u
        v = self.v

        z = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                z[i, k] = w[k]*x[i] + u[k]

        s = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                s[i, k] = sigma.s(z[i, k])

        s1 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                s1[i, k] = sigma.s1(s[i, k])

        s2 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                s2[i, k] = sigma.s2(s[i, k])

        N = np.zeros(n)
        for i in range(n):
            for k in range(H):
                N[i] += s[i, k]*v[k]

        dN_dx = np.zeros(n)
        for i in range(n):
            for k in range(H):
                dN_dx[i] += v[k]*s1[i, k]*w[k]

                
        d2N_dx2 = np.zeros(n)
        for i in range(n):
            for k in range(H):
                d2N_dx2[i] += v[k]*s2[i, k]*w[k]**2

        d2Yt_dx2 = np.zeros(n)
        for i in range(n):
            d2Yt_dx2[i] = self.__d2Yt_dx2f(x[i], N[i], dN_dx[i], d2N_dx2[i])

        return d2Yt_dx2
Exemplo n.º 3
0
    def __compute_error_gradient_debug(self, p, x):
        """Compute the gradient of the error function wrt network
        parameters (debug version)."""

        # Fetch the number of training points.
        n = len(x)

        # Unpack the network parameters (hsplit() returns views, so no copies made).
        H = len(self.v)
        (w, u, v) = np.hsplit(p, 3)

        # Compute the forward pass through the network.
        z = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                z[i, k] = w[k]*x[i] + u[k]

        s = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                s[i, k] = sigma.s(z[i, k])
            
        s1 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                s1[i, k] = sigma.s1(s[i, k])

        s2 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                s2[i, k] = sigma.s2(s[i, k])

        s3 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                s3[i, k] = sigma.s3(s[i, k])

        N = np.zeros(n)
        for i in range(n):
            for k in range(H):
                N[i] += v[k]*s[i, k]
            
        dN_dx = np.zeros(n)
        for i in range(n):
            for k in range(H):
                dN_dx[i] += v[k]*s1[i, k]*w[k]
            
        d2N_dx2 = np.zeros(n)
        for i in range(n):
            for k in range(H):
                d2N_dx2[i] += v[k]*s2[i, k]*w[k]**2

        dN_dw = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                dN_dw[i, k] = v[k]*s1[i, k]*x[i]
            
        dN_du = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                dN_du[i, k] = v[k]*s1[i, k]
            
        dN_dv = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                dN_dv[i, k] = s[i, k]
            
        d2N_dwdx = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d2N_dwdx[i, k] = v[k]*(s1[i, k] + s2[i, k]*w[k]*x[i])
            
        d2N_dudx = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d2N_dudx[i, k] = v[k]*s2[i, k]*w[k]
            
        d2N_dvdx = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d2N_dvdx[i, k] = s1[i, k]*w[k]

        d3N_dwdx2 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d3N_dwdx2[i, k] = v[k]*(2*s2[i, k]*w[k] + s3[i, k]*w[k]**2*x[i])
            
        d3N_dudx2 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d3N_dudx2[i, k] = v[k]*s3[i, k]*w[k]**2
            
        d3N_dvdx2 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d3N_dvdx2[i, k] = s2[i, k]*w[k]**2

        Yt = np.zeros(n)
        for i in range(n):
            Yt[i] = self.__Ytf(x[i], N[i])

        dYt_dx = np.zeros(n)
        for i in range(n):
            dYt_dx[i] = self.__dYt_dxf(x[i], N[i], dN_dx[i])

        d2Yt_dx2 = np.zeros(n)
        for i in range(n):
            d2Yt_dx2[i] = self.__d2Yt_dx2f(x[i], N[i], dN_dx[i], d2N_dx2[i])
            
        dYt_dw = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                dYt_dw[i, k] = x[i]*(1 - x[i])*dN_dw[i, k]
            
        dYt_du = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                dYt_du[i, k] = x[i]*(1 - x[i])*dN_du[i, k]

        dYt_dv = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                dYt_dv[i, k] = x[i]*(1 - x[i])*dN_dv[i, k]

        d2Yt_dwdx = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d2Yt_dwdx[i, k] = x[i]*(1 - x[i])*d2N_dwdx[i, k] + (1 - 2*x[i])*dN_dw[i, k]
            
        d2Yt_dudx = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d2Yt_dudx[i, k] = x[i]*(1 - x[i])*d2N_dudx[i, k] + (1 - 2*x[i])*dN_du[i, k]

        d2Yt_dvdx = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d2Yt_dvdx[i, k] = x[i]*(1 - x[i])*d2N_dvdx[i, k] + (1 - 2*x[i])*dN_dv[i, k]

        d3Yt_dwdx2 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d3Yt_dwdx2[i, k] = x[i]*(1 - x[i])*d3N_dwdx2[i, k] + 2*(1 - 2*x[i])*d2N_dwdx[i, k] - 2*dN_dw[i, k]

        d3Yt_dudx2 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d3Yt_dudx2[i, k] = x[i]*(1 - x[i])*d3N_dudx2[i, k] + 2*(1 - 2*x[i])*d2N_dudx[i, k] - 2*dN_du[i, k]

        d3Yt_dvdx2 = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                d3Yt_dvdx2[i, k] = x[i]*(1 - x[i])*d3N_dvdx2[i, k] + 2*(1 - 2*x[i])*d2N_dvdx[i, k] - 2*dN_dv[i, k]

        G = np.zeros(n)
        for i in range(n):
            G[i] = self.eq.Gf(x[i], Yt[i], dYt_dx[i], d2Yt_dx2[i])

        dG_dYt = np.zeros(n)
        for i in range(n):
            dG_dYt[i] = self.eq.dG_dYf(x[i], Yt[i], dYt_dx[i], d2Yt_dx2[i])

        dG_ddYtdx = np.zeros(n)
        for i in range(n):
            dG_ddYtdx[i] = self.eq.dG_ddYdxf(x[i], Yt[i], dYt_dx[i], d2Yt_dx2[i])

        dG_dd2Ytdx2 = np.zeros(n)
        for i in range(n):
            dG_dd2Ytdx2[i] = self.eq.dG_dd2Ydx2f(x[i], Yt[i], dYt_dx[i], d2Yt_dx2[i])

        dG_dw = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                dG_dw[i, k] = dG_dYt[i]*dYt_dw[i, k] + dG_ddYtdx[i]*d2Yt_dwdx[i, k] + dG_dd2Ytdx2[i]*d3Yt_dwdx2[i, k]
            
        dG_du = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                dG_du[i, k] = dG_dYt[i]*dYt_du[i, k] + dG_ddYtdx[i]*d2Yt_dudx[i, k] + dG_dd2Ytdx2[i]*d3Yt_dudx2[i, k]

        dG_dv = np.zeros((n, H))
        for i in range(n):
            for k in range(H):
                dG_dv[i, k] = dG_dYt[i]*dYt_dv[i, k] + dG_ddYtdx[i]*d2Yt_dvdx[i, k] + dG_dd2Ytdx2[i]*d3Yt_dvdx2[i, k]

        dE_dw = np.zeros(H)
        for k in range(H):
            for i in range(n):
                dE_dw[k] += 2*G[i]*dG_dw[i, k]
            
        dE_du = np.zeros(H)
        for k in range(H):
            for i in range(n):
                dE_du[k] += 2*G[i]*dG_du[i, k]

        dE_dv = np.zeros(H)
        for k in range(H):
            for i in range(n):
                dE_dv[k] += 2*G[i]*dG_dv[i, k]

        jac = np.zeros(3*H)
        for j in range(H):
            jac[j] = dE_dw[j]
        for j in range(H):
            jac[H + j] = dE_du[j]
        for j in range(H):
            jac[2*H + j] = dE_dv[j]

        return jac
Exemplo n.º 4
0
    def __train_delta_debug(self, x, opts=DEFAULT_OPTS):
        """Train using the delta method (debug version). """

        my_opts = dict(DEFAULT_OPTS)
        my_opts.update(opts)

        # Sanity-check arguments.
        assert len(x) > 0
        assert opts['maxepochs'] > 0
        assert opts['eta'] > 0
        assert opts['vmin'] < opts['vmax']
        assert opts['wmin'] < opts['wmax']
        assert opts['umin'] < opts['umax']

        # Determine the number of training points, and change notation for
        # convenience.
        n = len(x)  # Number of training points
        H = len(self.v)
        debug = my_opts['debug']
        verbose = my_opts['verbose']
        eta = my_opts['eta']  # Learning rate
        maxepochs = my_opts['maxepochs']  # Number of training epochs
        wmin = my_opts['wmin']  # Network parameter limits
        wmax = my_opts['wmax']
        umin = my_opts['umin']
        umax = my_opts['umax']
        vmin = my_opts['vmin']
        vmax = my_opts['vmax']

        # Create the hidden node weights, biases, and output node weights.
        w = np.random.uniform(wmin, wmax, H)
        u = np.random.uniform(umin, umax, H)
        v = np.random.uniform(vmin, vmax, H)

        # Initial parameter deltas are 0.
        dE_dw = np.zeros(H)
        dE_du = np.zeros(H)
        dE_dv = np.zeros(H)

        # Train the network.
        for epoch in range(maxepochs):
            if verbose:
                print('Starting epoch %d.' % epoch)

            # Compute the new values of the network parameters.
            for k in range(H):
                w[k] -= eta*dE_dw[k]

            for k in range(H):
                u[k] -= eta*dE_du[k]

            for k in range(H):
                v[k] -= eta*dE_dv[k]

            # Compute the input, the sigmoid function, and its derivatives, for
            # each hidden node and each training point.
            z = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    z[i, k] = w[k]*x[i] + u[k]

            s = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    s[i, k] = sigma.s(z[i, k])
            
            s1 = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    s1[i, k] = sigma.s1(s[i, k])

            s2 = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    s2[i, k] = sigma.s2(s[i, k])

            s3 = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    s3[i, k] = sigma.s3(s[i, k])
            
            # Compute the network output and its derivatives, for each
            # training point.
            N = np.zeros(n)
            for i in range(n):
                for k in range(H):
                    N[i] += v[k]*s[i, k]
            
            dN_dx = np.zeros(n)
            for i in range(n):
                for k in range(H):
                    dN_dx[i] += v[k]*s1[i, k]*w[k]
            
            d2N_dx2 = np.zeros(n)
            for i in range(n):
                for k in range(H):
                    d2N_dx2[i] += v[k]*s2[i, k]*w[k]**2

            dN_dw = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    dN_dw[i, k] = v[k]*s1[i, k]*x[i]
            
            dN_du = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    dN_du[i, k] = v[k]*s1[i, k]
            
            dN_dv = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    dN_dv[i, k] = s[i, k]
            
            d2N_dwdx = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d2N_dwdx[i, k] = v[k]*(s1[i, k] + s2[i, k]*w[k]*x[i])
            
            d2N_dudx = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d2N_dudx[i, k] = v[k]*s2[i, k]*w[k]
            
            d2N_dvdx = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d2N_dvdx[i, k] = s1[i, k]*w[k]

            d3N_dwdx2 = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d3N_dwdx2[i, k] = v[k]*(2*s2[i, k]*w[k] + s3[i, k]*w[k]**2*x[i])
            
            d3N_dudx2 = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d3N_dudx2[i, k] = v[k]*s3[i, k]*w[k]**2
            
            d3N_dvdx2 = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d3N_dvdx2[i, k] = s2[i, k]*w[k]**2
            
            # Compute the value of the trial solution and its derivatives,
            # for each training point.
            Yt = np.zeros(n)
            for i in range(n):
                Yt[i] = self.__Ytf(x[i], N[i])
            
            dYt_dx = np.zeros(n)
            for i in range(n):
                dYt_dx[i] = self.__dYt_dxf(x[i], N[i], dN_dx[i])

            d2Yt_dx2 = np.zeros(n)
            for i in range(n):
                d2Yt_dx2[i] = self.__d2Yt_dx2f(x[i], N[i], dN_dx[i], d2N_dx2[i])
            
            dYt_dw = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    dYt_dw[i, k] = x[i]*(1 - x[i])*dN_dw[i, k]
            
            dYt_du = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    dYt_du[i, k] = x[i]*(1 - x[i])*dN_du[i, k]

            dYt_dv = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    dYt_dv[i, k] = x[i]*(1 - x[i])*dN_dv[i, k]

            d2Yt_dwdx = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d2Yt_dwdx[i, k] = x[i]*(1 - x[i])*d2N_dwdx[i, k] + (1 - 2*x[i])*dN_dw[i, k]
            
            d2Yt_dudx = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d2Yt_dudx[i, k] = x[i]*(1 - x[i])*d2N_dudx[i, k] + (1 - 2*x[i])*dN_du[i, k]

            d2Yt_dvdx = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d2Yt_dvdx[i, k] = x[i]*(1 - x[i])*d2N_dvdx[i, k] + (1 - 2*x[i])*dN_dv[i, k]

            d3Yt_dwdx2 = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d3Yt_dwdx2[i, k] = x[i]*(1 - x[i])*d3N_dwdx2[i, k] + 2*(1 - 2*x[i])*d2N_dwdx[i, k] - 2*dN_dw[i, k]

            d3Yt_dudx2 = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d3Yt_dudx2[i, k] = x[i]*(1 - x[i])*d3N_dudx2[i, k] + 2*(1 - 2*x[i])*d2N_dudx[i, k] - 2*dN_du[i, k]

            d3Yt_dvdx2 = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    d3Yt_dvdx2[i, k] = x[i]*(1 - x[i])*d3N_dvdx2[i, k] + 2*(1 - 2*x[i])*d2N_dvdx[i, k] - 2*dN_dv[i, k]

            # Compute the value of the original differential equation for
            # each training point, and its derivatives.
            G = np.zeros(n)
            for i in range(n):
                G[i] = self.eq.Gf(x[i], Yt[i], dYt_dx[i], d2Yt_dx2[i])

            dG_dYt = np.zeros(n)
            for i in range(n):
                dG_dYt[i] = self.eq.dG_dYf(x[i], Yt[i], dYt_dx[i], d2Yt_dx2[i])

            dG_ddYtdx = np.zeros(n)
            for i in range(n):
                dG_ddYtdx[i] = self.eq.dG_ddYdxf(x[i], Yt[i], dYt_dx[i], d2Yt_dx2[i])

            dG_dd2Ytdx2 = np.zeros(n)
            for i in range(n):
                dG_dd2Ytdx2[i] = self.eq.dG_dd2Ydx2f(x[i], Yt[i], dYt_dx[i], d2Yt_dx2[i])

            dG_dw = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    dG_dw[i, k] = dG_dYt[i]*dYt_dw[i, k] + dG_ddYtdx[i]*d2Yt_dwdx[i, k] + dG_dd2Ytdx2[i]*d3Yt_dwdx2[i, k]
            
            dG_du = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    dG_du[i, k] = dG_dYt[i]*dYt_du[i, k] + dG_ddYtdx[i]*d2Yt_dudx[i, k] + dG_dd2Ytdx2[i]*d3Yt_dudx2[i, k]

            dG_dv = np.zeros((n, H))
            for i in range(n):
                for k in range(H):
                    dG_dv[i, k] = dG_dYt[i]*dYt_dv[i, k] + dG_ddYtdx[i]*d2Yt_dvdx[i, k] + dG_dd2Ytdx2[i]*d3Yt_dvdx2[i, k]

            # Compute the error function for this epoch.
            E = 0
            for i in range(n):
                E += G[i]**2

            # Compute the partial derivatives of the error with respect to the
            # network parameters.
            dE_dw = np.zeros(H)
            for k in range(H):
                for i in range(n):
                    dE_dw[k] += 2*G[i]*dG_dw[i, k]
            
            dE_du = np.zeros(H)
            for k in range(H):
                for i in range(n):
                    dE_du[k] += 2*G[i]*dG_du[i, k]

            dE_dv = np.zeros(H)
            for k in range(H):
                for i in range(n):
                    dE_dv[k] += 2*G[i]*dG_dv[i, k]
  
            # Compute the RMS error for this epoch.
            rmse = sqrt(E/n)
            if opts['verbose']:
                print(epoch, rmse)

        # Save the optimized parameters.
        self.w = w
        self.u = u
        self.v = v