Regressão Linear com muitas variáveis
Descrição do Produto
Regress˜ao Linear com muitas vari´aveis Manuel Leiria August 7, 2016
Abstract A regress˜ ao linear com muitas vari´aveis ´e uma generaliza¸c˜a matem´atica da Regress˜ao linear com uma vari´ avel, j´ a descrita no artigo anterior (Regress˜ao Linear com uma vari´avel). Tudo o que foi referido para uma vari´ avel, tamb´em se aplica ao caso de muitas vari´aveis (fun¸c˜ao de custo, gradiente descendente,...).
1
Introdu¸c˜ ao
Segue-se a nota¸c˜ ao utilizada para equa¸c˜oes com muitas vari´aveis de input: (i)
xj = valor da vari´ avel j (feature) no exemplo de treino i. Em termos matriciais ´e o valor do componente da linha i, coluna j. xi = vector coluna de todos os inputs das vari´aveis do exemplo de treino i. m = N´ umero de exemplos de treino. n = |xi | (n´ umero de inputs ou features).
A fun¸c˜ao de hip´ otese para muitas vari´aveis ´e:
hθ (x) = θ0 + θ1 x1 + θ2 x2 + ... + θn xn
(1)
Retomando o exemplo dos pre¸cos da venda de apartamentos em fun¸c˜ao das suas caracter´ısticas, podemos pensar, por exemplo que θ0 ´e o pre¸co b´asico da casa, θ1 ser´a o pre¸co por metro quadrado, θ2 o pre¸co por andar, etc. Ent˜ao x1 representa o n´ umero de metros quadrados da casa, x2 o n´ umero de andares, etc.
1
Introduzindo a vari´ avel dummy x0 = 1 para termos as dimens˜oes alinhadas, podemos reescrever a equa¸c˜ao 1 em termos matriciais (relembro que uma das propriedades b´asicas de multiplica¸c˜ ao de matrizes ´e que o n´ umero de colunas da primeira matriz tem de ser igual ao n´ umero de linhas da segunda matriz) da seguinte forma:
hθ (x) = [θ0
x1 T θn ] .. = θ x . xn
···
θ1
x0
(2)
Se tivermos m exemplos de treino, cada um com n features, podemos construir a seguinte matriz:
(1) x 0 (1) x1 X= (1) xn
(2)
...
(2)
...
x0
x1
.. . (2)
xn
...
(m)
x0
1
(1) (m) x1 x1 = (m) (1) xn xn
1
...
(2)
x1
1
(m) x1 (m) xn
... .. .
(2)
xn
...
(3)
Portanto, nesta representa¸c˜ ao, a primeira coluna representa o primeiro exemplo de treino, a segunda coluna, o segundo exemplo e por ai fora. Estamos em condi¸c˜ oes de definir hθ (X) como um vector linha que nos d´a o valor de hθ (x) em cada um dos m exemplos de treino: (1)
(1)
hθ (X) = [θ0 x0 +θ1 x1 +. . .+θn x(1) n
(2)
(2)
θ0 x0 +θ1 x1 +. . .+θn x(2) n
...
(m)
(m)
θ0 x0 +θ1 x1 +. . .+θn x(m) n ] (4)
ou seja,
hθ (X) = [θ0
θ1
···
(1) x 0 (1) x1 θn ] (1) xn
(2)
x0
(2) x1
(2)
x0
...
(m) x1
...
xn
.. . xn
(m)
...
(m)
T =θ X
(5)
Nota: esta vers˜ ao da fun¸c˜ ao de hip´otese assume que a matrix X e o vector θ guardam os valores na seguinte forma: (1) x0 X= (1) x1
(2) x0 (2) x2
(3) x0 ,θ (3) x3
2
θ0 = , θ1
(6)
Eu prefiro usar uma abordagem alternativa, onde cada linha corresponde a um exemplo de treino (row-wise). Neste caso: (1) x 0 X = x(2) 0 (3) x0
(1)
x1
θ0 (2) x1 , θ = , θ1 (3) x1
(7)
Acho esta abordagem mais intuitiva, at´e porque normalmente recebemos os dados de teste (seja a partir de um ficheiro csv ou bd) neste formato, onde cada linha corresponde a um exemplo de treino. Neste formato, a fun¸c˜ ao de hip´ otese escreve-se:
hθ (X) = Xθ
(8)
´ claro que nesta representa¸c˜ E ao hθ (X) ´e um vector coluna.
2
Fun¸c˜ ao de custo
A fun¸c˜ao de custo, tal como j´ a vimos, ´e: m
1 X J(θ) = (hθ (x(i) − y (i) )2 2m
(9)
i=1
ou, melhor ainda, na sua forma vectorial: J(θ) =
1 (Xθ − ~y )T (Xθ − ~y ) 2m
(10)
onde ~y ´e o vector de todos os valores y (no nosso exemplo ser´a o pre¸co do apartamento, a vari´avel sobre a qual queremos fazer previs˜oes.
3
Gradiente Descendente
A equa¸c˜ao do gradiente descendente, ´e (ver Regress˜ao Linear com uma vari´avel para mais informa¸c˜oes): (i)
1 θ0 := θ0 − α m
Pm
(i) )
− y (i) )x0
1 θ1 := θ1 − α m
Pm
(i) )
− y (i) )x(i)
i=1 (hθ (x i=1 (hθ (x
3
... ou seja, repetir 1 θj := θj − α m
Pm
i=1 (hθ (x
(i) )
(i)
− y (i) )xj
at´e convergir. (i)
N˜ao esquecer que x0 = 1 sempre (vari´avel dummy criada s´o para se conseguir generalizar a equa¸c˜ao). Mais interessante ´e a sua representa¸c˜ao vectorial:
θ := θ − α∇J(θ)
(11)
onde ∇J(θ) ´e um vector coluna da forma:
∂J(θ) ∂θ0 ∂J(θ) ∂θ1
∇J(θ) = . , ..
(12)
∂J(θ) ∂θn
Calculando as derivadas parciais, obtemos para o gradiente:
∇J(θ) =
1 T X (Xθ − ~y ) m
(13)
Substituindo esta express˜ ao na equa¸c˜ao (11) obtemos, finalmente, a express˜ao do gradiente descendente na sua forma matricial (ou vectorial): θ := θ −
4 4.1
α T X (Xθ − ~y ) m
(14)
Exemplo pr´ atico com implementa¸ c˜ ao em Java An´ alise e pr´ e-processamento dos dados
NOTA: todos os ficheiros (classes java, dados, pdf) est˜ao aqui
Vamos come¸car por olhar para os dados. Tenho um ficheiro (housePrice.txt) com 47 registos. A primeira coluna representa o tamanho em m2 do apartamento, a segunda coluna diz-nos quantos quartos o apartamento tem (estas s˜ao as vari´aveis de input x ou features) e
4
por fim, na terceira e u ´ltima coluna, est´a o pre¸co
Table 1: Pre¸co dos apartamentos em Lisboa. Tamanho (m2 )
N´ um. quartos
Pre¸co (euros)
195.5
3
399900
148.6
3
329900
223.0
3
369000
131.6
2
232000
278.7
4
539900
184.4
4
299900
142.5
3
314900
132.6
3
198999
128.2
3
212000
138.8
3
242500
...
...
...
79.2
2
179900
172.1
4
299900
111.8
3
239500
Vamos ver o pre¸co em fun¸c˜ ao do tamanho: C´odigo Python
import matplotlib.pyplot as plt
work_dir = ’/home/manuel/tools/adalineProcesses/mlearning/dataFiles/’ input_file = ’housePrice’ ext = ’.txt’ file_to_process = work_dir + input_file + ext x1 = [] #tamanho em m^2 x2 = [] #num. quartos
5
y = [] #preco de venda f = open(file_to_process, ’r’) for line in f: values = line.split(’,’) x1.append(float(values[0])) x2.append(float(values[1])) y.append(float(values[2])) f.close() plt.scatter(x1,y) plt.xlabel(’Tamanho em m^2’) plt.ylabel(’Preo em euros’) plt.show()
Olhando para a tabela, podemos constatar que os valores do tamanho do apartamento s˜ ao muito superiores aos valores do n´ umero de quartos (pelo menos por uma ordem de 10).Quando as features diferem por ordens de magnitude, normalizar os falores (feature scaling) pode fazer o gradiente descendente convergir muito mais depressa. Isto porque θ desce muito mais depressa em intervalos pequenos e ´e muito lento em intervalos grandes. Uma forma de prevenir oscila¸c˜ oes desnecess´arias e ineficientes na descida do gradiente, ´e normalizar os valores. Idealmente ter qualquer coisa do g´enero −1 ≤ xi ≤ 1 ou −0.5 ≤ xi ≤ 0.5
6
Uma das t´ecnicas utilizadas para nos auxiliar nesta tarefa ´e a normaliza¸c˜ao pela m´edia e desvio padr˜ao: xi :=
xi − µ i σi
(15)
Portanto, o que h´ a a fazer, ´e para cada feature nos dados, subtrair a m´edia e depois dividir pelo desvio padr˜ ao. O desvio padr˜ ao d´a-nos uma forma de medir a varia¸c˜ao que existe no intervalo de valores de cada feature.
4.2 4.2.1
Implementa¸ c˜ ao Carregar os dados
Classe que vai correr a regress˜ ao: package pt.mleiria.machinelearning;
import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import pt.mleiria.machinelearning.matrixAlgebra.Matrix;
/** * * @author manuel */ public class LinearRegMultiple {
private static final String path = "/home/manuel/tools/adalineProcesses/mlearning/dataFiles/"; private final static String dataFile = path + "housePrice.txt";
7
private final static String costHistory = path +"JGDM.txt";
public static void main(String[] args) { try { double[][] rawData = loadFileToComponents(dataFile, ","); Matrix matrix = new Matrix(rawData); //We can check the data loaded System.out.println(matrix.toString()); } catch (Exception ex) { Logger.getLogger(LinearRegMultiple.class.getName()).log(Level.SEVERE, null, ex); } }
/** * load a file in csv style into a matrix, 1.34,2.34,0.3 13.45,0.2231,1.33 * * @param pathToFile * @param separator * @return * @throws java.io.FileNotFoundException */ public static double[][] loadFileToComponents(final String pathToFile, final String separator) throws FileNotFoundException, IOException { final List rows; try (BufferedReader br = new BufferedReader(new FileReader(pathToFile))) { String line; rows = new ArrayList(); while ((line = br.readLine()) != null) { rows.add(line.split(separator)); }
8
} double[][] data = new double[rows.size()][]; for (int i = 0; i < rows.size(); i++) { final String[] rowArr = rows.get(i); final int colSize = rowArr.length; data[i] = new double[colSize]; for (int j = 0; j < colSize; j++) { data[i][j] = Double.parseDouble(rowArr[j]); } } return data; } } Esta classe tem o public static void main(String[] args) que vai ser usada para correr o programa e tem um m´etodo auxiliar (loadFileToComponents(...)) que carrega um ficheiro estilo csv (dados separados por v´ırgulas) para um double[][]. Correndo este c´odigo, obtenho um objecto Matrix com 47 linhas e 3 colunas. Segundo passo ser´ a separar as features dos target values, ou seja, x para um lado e y para o outro (vou-me fixar no peda¸co de c´ odigo dentro do public static void main(...) para n˜ao estar sempre a repetir: try { double[][] rawData = loadFileToComponents(dataFile, ","); Matrix matrix = new Matrix(rawData); //We can check the data loaded System.out.println(matrix.toString()); //split the matrix in x (features) and y (target value) Matrix[] dMatrix = matrix.split(1); //Let’s see: Matrix x = dMatrix[0]; Matrix y = dMatrix[1]; System.out.println(x.toString());
9
System.out.println(y.toString()); } O m´etodo split pertence ` a classe Matrix.java: /** * Splits the receiver in two Matrices * * @param numCols number of columns of the Matrix[1] * @return Matrix[2] where Matrix[0] = Matrix[rows, cols-numCols] Matrix[1] * = Matrix[rows, numCols */ public Matrix[] split(final int numCols) { if (numCols >= columns()) { throw new IllegalArgumentException("numCols must be smaller than columns"); } final int rows = this.rows(); final int cols = this.columns(); final int diffCols = cols - numCols; final double[][] a = new double[rows][diffCols]; final double[][] b = new double[rows][numCols]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { if (j < diffCols) { a[i][j] = components[i][j]; } else { b[i][diffCols - j] = components[i][j]; } } } final Matrix[] result = new Matrix[2];
10
final Matrix aa = new Matrix(a); final Matrix bb = new Matrix(b); result[0] = aa; result[1] = bb; return result;
} Tenho, ent˜ ao duas matrizes, uma com as features x e outra com o y. Este m´etodo tem de ser revisto porque nos casos em que uma das matrizes final ´e uma coluna (nx1) em vez de uma matriz posso ter um vector que sempre ´e mais leve. Um caso a ver... Pr´oximo passo: normalizar (feature normalization) as features (matriz x ). Para normalizar, e porque pode haver diferentes formas de normalizar os dados, comecei por criar um interface: package pt.mleiria.machinelearning.preprocess;
import pt.mleiria.machinelearning.matrixAlgebra.Matrix; /** * * @author manuel */ public interface FeatureNormalization {
Matrix normalize(final Matrix matrix); } e tenho a seguinte implementa¸c˜ ao: package pt.mleiria.machinelearning.preprocess;
import pt.mleiria.machinelearning.matrixAlgebra.Matrix; import pt.mleiria.machinelearning.statistics.StatisticalMoments;
/**
11
* * @author manuel */ public class FeatNormMeanStdev implements FeatureNormalization {
private double[] mean; private double[] stdev;
/** * new Matrix = (elements - mean)/std * * @param matrix the Matrix to be normalizes * @return the normalized matrix */ @Override public Matrix normalize(final Matrix matrix) { mean = new double[matrix.columns()]; stdev = new double[matrix.columns()];
final int rows = matrix.rows(); final int columns = matrix.columns(); double[][] components = matrix.toComponents(); /** * The normalized matrix */ final double[][] newComponents = new double[rows][columns]; for (int i = 0; i < columns; i++) { final StatisticalMoments sm = new StatisticalMoments(); int j = 0; for (j = 0; j < rows; j++) { sm.accumulate(components[j][i]); }
12
mean[i] = sm.average(); stdev[i] = sm.standardDeviation(); for (j = 0; j < rows; j++) { newComponents[j][i] = (components[j][i] - mean[i]) / stdev[i]; } } return new Matrix(newComponents); } /** * * @return an array with the mean of all columns */ public double[] getMean() { return mean; } /** * * @return an array with the stdev of all columns */ public double[] getStdev() { return stdev; } } Aqui est˜ao a acontecer algumas coisas, sendo que o principal a referir ´e que estou a fazer uso de uma nova classe (StatisticalMoments.java). Esta classe acumula os valores e retorna os v´arios momentos estat´ısticos, nomeadamente a m´edia, a variˆancia, skweness e kurtosis. Vamos ver: package pt.mleiria.machinelearning.statistics;
/** * * @author manuel
13
*/ public class StatisticalMoments { /** * Vector containing the points */ protected double[] moments; /** * Default constructor methods: declare space for 5 moments. */ public StatisticalMoments() { this(5); } /** * * @param n number of moments to accumulate */ public StatisticalMoments(final int n) { moments = new double[n]; reset(); } /** * * @param x */ public void accumulate(final double x) { double value = 1.0; for (int n = 0; n < moments.length; n++) { moments[n] += value; value *= x; } } /**
14
* @return double average. */ public double average() { return moments[1] / moments[0]; } /** * The kurtosis measures the sharpness of the distribution near the maximum. * Note: The kurtosis of the Normal distribution is 0 by definition. * * @return double kurtosis. */ public double kurtosis() throws ArithmeticException { if (moments[0] < 4) { return Double.NaN; } double x1 = average(); double x2 = moments[2] / moments[0]; double x3 = moments[3] / moments[0]; double x4 = moments[4] / moments[0]; double xSquared = x1 * x1; double m4 = x4 - (4 * x1 * x3) + 3 * xSquared * (2 * x2 - xSquared); double kFact = moments[0] * (moments[0] + 1) / ((moments[0] - 1) * (moments[0] - 2) * (moments[0] - 3)); double kConst = 3 * (moments[0] - 1) * (moments[0] - 1) / ((moments[0] - 2) * (moments[0] - 3)); x4 = variance(); x4 *= x4; return kFact * (m4 * moments[0] / x4) - kConst; }
15
/** * @return double skewness. */ public double skewness() throws ArithmeticException { if (moments[0] < 3) { return Double.NaN; } double x1 = average(); double x2 = moments[2] / moments[0]; double x3 = moments[3] / moments[0]; double m3 = x3 + x1 * (2 * x1 * x1 - 3 * x2); x1 = standardDeviation(); x2 = x1 * x1; x2 *= x1; return m3 * moments[0] * moments[0] / (x2 * (moments[0] - 1) * (moments[0] - 2)); } /** * Returns the standard deviation. May throw divide by zero exception. * * @return double standard deviation. */ public double standardDeviation() { return Math.sqrt(variance()); } /** * Unnormalized central moment of 2nd order (needed to compute the t-test). * * @return double */ public double unnormalizedVariance() {
16
double average = average(); return moments[2] - average * average * moments[0]; } /** * Note: the variance includes the Bessel correction factor. * * @return double variance. */ public double variance() throws ArithmeticException { if (moments[0] < 2) { return Double.NaN; } double average = average(); return (moments[0] / (moments[0] - 1)) * (moments[2] / moments[0] - average * average); } /** * Reset all counters */ private void reset() { for (int i = 0; i < moments.length; i++) { moments[i] = 0; } } } Vamos normalizar: try { double[][] rawData = loadFileToComponents(dataFile, ","); Matrix matrix = new Matrix(rawData); //We can check the data loaded System.out.println(matrix.toString());
17
//split the matrix in x (features) and y (target value) Matrix[] dMatrix = matrix.split(1); //Let’s see: Matrix x = dMatrix[0]; Matrix y = dMatrix[1]; System.out.println(x.toString()); System.out.println(y.toString()); //Feature normalization final FeatureNormalization ftn = new FeatNormMeanStdev(); final Matrix xNorm = ftn.normalize(x); //Check it System.out.println(xNorm.toString());
} Vamos agora faze uso da classe GradientDescent.java. Esta classe extende a IteratorProcessor.java que ´e uma classe abstracta gen´erica para processos iterativos. try { double[][] rawData = loadFileToComponents(dataFile, ","); Matrix matrix = new Matrix(rawData); //We can check the data loaded System.out.println(matrix.toString()); //split the matrix in x (features) and y (target value) Matrix[] dMatrix = matrix.split(1); //Let’s see: Matrix x = dMatrix[0]; Matrix y = dMatrix[1]; System.out.println(x.toString()); System.out.println(y.toString()); //Feature normalization final FeatureNormalization ftn = new FeatNormMeanStdev(); final Matrix xNorm = ftn.normalize(x);
18
//Check it System.out.println(xNorm.toString()); //alpha value double alpha = 0.01; //Num max iter int numIter = 400; //desired precision double precision = 0.00001; GradientDescent gd = new GradientDescent(xNorm, y, alpha); gd.setMaximumIterations(numIter); gd.setDesiredPrecision(precision); gd.evaluate(); saveArrayToFile(costHistory, gd.getCostHistory()); } ´ um utilit´ario para O m´etodo saveArrayToFile() pertence `a classe LinearRegMultiple.java. E gravar os resultados em ficheiro. O construtor do GradientDescent.java recebe trˆes parˆametros, a matrix x normalizada, a matrix y (ou vector coluna) e o α que optei por come¸car com um valor de 0.01 mas pode ser reajustado. Fazemos tamb´em o set do n´ umero m´aximo de iterac¸c˜oes e da precis˜ao desejada. O processo iterativo para quando um deles for alcan¸cado. O m´etodo gd.evaluate vai at´e ` a classe abstracta IteratorPorcessor.java: public abstract class IteratorProcessor { //Code...
/** * Performs the iterative process */ public void evaluate() { iterations = 0; initializeIterations(); while (iterations++ < maximumIterations) {
19
precision = evaluateIteration(); if (hasConverged()) { log.info("Converged at iteration: [" + iterations + "]"); log.info("Converged with precision:[" + precision + "]"); break; } } finalizeIterations(); } //more code } onde initializeIterations() e evaluateIteration() est˜a overrided na classe GradientDescent.java: @Override public void initializeIterations() { costHistory = new double[getMaximumIterations() + 1]; setFeaturesX(featuresX.addOnes()); setTheta(new Matrix(featuresX.columns(), 1)); computeCost(); } /** * */ private void computeCost() { double coeff = 1.0 / (2.0 * dataSize); final Matrix a = featuresX.multiply(theta); final Matrix b = a.subtract(outputY); final Matrix c = b.transpose(); final Matrix d = c.multiply(b); final Matrix result = d.multiply(coeff); costHistory[iterations] = result.component(0, 0); }
20
/** * theta = theta - (alpha / m) * X’ * (X * theta - y); * * b = X * theta * c = b - y * d = X’ * c * e = (alpha/m) * d * * @return */ @Override public double evaluateIteration() { double coeff = (alpha / (double) dataSize); Matrix b = featuresX.multiply(theta); Matrix c = b.subtract(outputY); Matrix d = featuresX.transpose(); Matrix e = d.multiply(c); Matrix f = e.multiply(coeff); theta = theta.subtract(f); computeCost(); double precision = costHistory[iterations] - costHistory[iterations 1]; return Math.abs(precision); } O m´etodo computeCost() refere-se a` eq.(10), para o c´alculo de J(θ). O m´etodo evaluateIteration() refere-se `a eq.(14). O Hist´orico de J(θ) ´e guardado porque serve para analisar como correram as itera¸c˜oes e, eventualemte, afinar alguns parˆametros (e.g. α) Note-se que no m´etodo initializeIterations temos featuresX.addOnes(). Estamos a adicionar uma coluna de 1 na posi¸c˜ ao 0, tal como falado na parte te´orica. Correndo o m´etodo public static void main(String[] args), obtemos os valores de θ. Adicionalmente ´e gravado um ficheiro (JGDM.txt) com o hist´ orico da fun¸c˜ao de custo, J(θ).
21
Vamos, ent˜ ao analisar os resultados. Comecemos por ver a evolu¸cao da fun¸c˜ao de custo, J(θ): C´odigo Python import matplotlib.pyplot as plt
work_dir = ’/home/manuel/tools/adalineProcesses/mlearning/dataFiles/’ input_file = ’JGDM’ ext = ’.txt’ file_to_process = work_dir + input_file + ext num_iter = [] #Numero de iteraccoes cost_func = [] #Funcao de custo
f = open(file_to_process, ’r’) for line in f: values = line.split(’,’) num_iter.append(int(values[0])) cost_func.append(float(values[1]))
f.close()
plt.plot(num_iter,cost_func) plt.xlabel(’Num. Iter.’) plt.ylabel(’J(theta)’) plt.show()
22
Nota-se a convergˆencia da fun¸c˜ ao de custo. Pode-se, no entanto, redimensionar o parˆametro α, voltar a correr e analisar novamente a evolu¸c˜ao. Se constatarmos que J(θ) aumenta, provavelmente temos de baixar o α. Para obtermos os valores de θ, fazemos (neste caso θ0
θ1
θ2 e θ ´e uma matriz coluna) temos:
gd.getTheta().component(0, 0) gd.getTheta().component(1, 0) gd.getTheta().component(2, 0) Por fim, e o grande objectivo: prever o pre¸co de um apartamento que n˜ao est´a nos dados. Tenho um apartamento para venda com 140 m2 e 3 quartos. Quanto vale? Tenho θ0 , θ1 , θ2 dados pelo c´ odigo supra. Tenho x0 = 1, x1 = 140, x2 = 3. Ent˜ao posso usar a eq. (1) para n = 3: hθ (x) = θ0 x0 + θ1 x1 + θ2 x2 try { double[][] rawData = loadFileToComponents(dataFile, ","); Matrix matrix = new Matrix(rawData); //We can check the data loaded System.out.println(matrix.toString()); //split the matrix in x (features) and y (target value) Matrix[] dMatrix = matrix.split(1); //Let’s see: Matrix x = dMatrix[0];
23
Matrix y = dMatrix[1]; System.out.println(x.toString()); System.out.println(y.toString()); //Feature normalization final FeatureNormalization ftn = new FeatNormMeanStdev(); final Matrix xNorm = ftn.normalize(x); //Check it System.out.println(xNorm.toString()); //alpha value double alpha = 0.01; //Num max iter int numIter = 400; //desired precision double precision = 0.00001; GradientDescent gd = new GradientDescent(xNorm, y, alpha); gd.setMaximumIterations(numIter); gd.setDesiredPrecision(precision); gd.evaluate(); saveArrayToFile(costHistory, gd.getCostHistory());
double x1 = 140.0; double x2 = 3; double yPrev = gd.getTheta().component(0, 0) + ((x1 - ((FeatNormMeanStdev)ftn).getMean()[0])/ ((FeatNormMeanStdev)ftn).getStdev()[0]) * gd.getTheta().component(1, 0) + ((x2 - ((FeatNormMeanStdev)ftn).getMean()[1])/ ((FeatNormMeanStdev)ftn).getStdev()[1]) * gd.getTheta().component(2, 0); System.out.println("Previsao:" + yPrev);
}
24
Aten¸c˜ao porque os valores tˆem de ser normalizados, `a semelha¸ca dos outros, antes de serem utilizados. A classe FeatNormMeanStdev.java guarda, convenientemente, as m´edias e desvio padr˜ao calculados para serem reutilizados. Finalmente, a previs˜ ao de venda d´ a: Previsao:271289.7561951509 euros
25
Lihat lebih banyak...
Comentários