رگرسیون خطی با استفاده از الگوریتم ژنتیک همراه با کدهای پایتون
تخمین قیمت ماشین با استفاده از رگرسیون خطی مبتنی بر الگوریتم ژنتیک
مسائل یادگیری ماشین اگر از نوع بانظارت باشند، به دو دسته ی کلی کلاسیفیکیشن و رگرسیون تقسیم می شوند. در مسائل کلاسیفیکیشن چیزی که باید یاد گرفته شود. از نوع کلاس یا دسته یا به عبارتی یک ویژگی categorical است. اما در مسائل رگرسیون ویژگی که قرار است یاد گرفته شود و پیش بینی شود از نوع عددی یا numerical است.
در مسئله ی پیش رو قرار است قیمت ماشین که یک ویژگی عددی است از روی سایر ویژگی ها یاد گرفته شود. بنابراین ما با یک مسئله رگرسیون روبرو هستیم. برای این کار ابتدا دیتاست مربوطه لود شده و ویژگی های غیر عددی آن جدا شده است. البته این امکان وجود داشت که ویژگی های غیرعددی را نیز به عددی تبدیل کرده و از آن ها نیز استفاده کرد.
رگرسیون خطی خود به تنهایی قادر به حل این مسئله است اما در اینجا از الگوریتم ژنتیک برای حل این مسئله استفاه شده است. به این شکل که مسئله به صورت یافتن خط مناسب y=ax+b تعریف می شود که در آن x یک بردار شامل 14 مولفه (متناظر با تعداد ویژگی ها) خواد بود. همین بردار کروموزم های ما را تشکیل خواهد داد. در ادامه جمعیت اولیه تشکیل شده و در هر مراحله فرآیندهای crossover و mutation نیز انجام خواهند گرفت. در نهایت ضرایب بهینه محاسبه خواهند شد.
from random import random, sample, choice
from math import floor
from tqdm import tqdm
from numpy import array, dot, mean
from numpy.linalg import pinv
from sys import exit
import pandas as pd
import math
def generate_data():
data = pd.read_csv('C:\\Users\\sobhan\\Desktop\\javadi 1400\\Codes\\Linear Regression\\CarPrice_Assignment.csv')
x=data[["symboling", "wheelbase","carlength","carwidth","carheight","curbweight","enginesize","boreratio","stroke","compressionratio","horsepower","peakrpm","citympg","highwaympg"]]
y=data["price"]
return array(x), array(y)
def multiple_linear_regression(inputs, outputs):
X, Y = array(inputs), array(outputs)
X_t, Y_t = X.transpose(), Y.transpose()
coeff = dot((pinv((dot(X_t, X)))), (dot(X_t, Y)))
Y_p = dot(X, coeff)
Y_mean = mean(Y)
SST = array([(i - Y_mean) ** 2 for i in Y]).sum()
SSR = array([(i - j) ** 2 for i, j in zip(Y, Y_p)]).sum()
COD = (1 - (SSR / SST)) * 100.0
av_error = (SSR / len(Y))
return {'COD': COD, 'coeff': coeff, 'error': av_error}
def check_termination_condition(best_individual):
if ((best_individual['COD'] >= 99.0)
or (generation_count == max_generations)):
return True
else:
return False
def create_individual(individual_size):
return [random() for i in range(individual_size)]
def create_population(individual_size, population_size):
return [create_individual(individual_size) for i in range(population_size)]
def get_fitness(individual, inputs):
predicted_outputs = dot(array(inputs), array(individual))
output_mean = mean(outputs)
SST = array(
[(i - output_mean) ** 2 for i in outputs]).sum()
SSR = array(
[(i - j) ** 2 for i, j in zip(outputs, predicted_outputs)]).sum()
COD = (1 - (SSR / SST)) * 100.0
av_error = math.sqrt((SSR / len(outputs)))/len(outputs)
return {'COD': COD, 'error': av_error, 'coeff': individual}
def evaluate_population(population):
fitness_list = [get_fitness(individual, inputs)
for individual in tqdm(population)]
error_list = sorted(fitness_list, key=lambda i: i['error'])
best_individuals = error_list[: selection_size]
best_individuals_stash.append(best_individuals[0]['coeff'])
print('Error: ', best_individuals[0]['error'],
'COD: ', best_individuals[0]['COD'])
return best_individuals
def crossover(parent_1, parent_2):
child = {}
loci = [i for i in range(0, individual_size)]
loci_1 = sample(loci, floor(0.5*(individual_size)))
loci_2 = [i for i in loci if i not in loci_1]
chromosome_1 = [[i, parent_1['coeff'][i]] for i in loci_1]
chromosome_2 = [[i, parent_2['coeff'][i]] for i in loci_2]
child.update({key: value for (key, value) in chromosome_1})
child.update({key: value for (key, value) in chromosome_2})
return [child[i] for i in loci]
def mutate(individual):
loci = [i for i in range(0, individual_size)]
no_of_genes_mutated = floor(probability_of_gene_mutating*individual_size)
loci_to_mutate = sample(loci, no_of_genes_mutated)
for locus in loci_to_mutate:
gene_transform = choice([-1, 1])
change = gene_transform*random()
individual[locus] = individual[locus] + change
return individual
def get_new_generation(selected_individuals):
parent_pairs = [sample(selected_individuals, 2)
for i in range(population_size)]
offspring = [crossover(pair[0], pair[1]) for pair in parent_pairs]
offspring_indices = [i for i in range(population_size)]
offspring_to_mutate = sample(
offspring_indices,
floor(probability_of_individual_mutating*population_size)
)
mutated_offspring = [[i, mutate(offspring[i])]
for i in offspring_to_mutate]
for child in mutated_offspring:
offspring[child[0]] = child[1]
return offspring
inputs, outputs = generate_data()
individual_size = len(inputs[0])
population_size = 1000
selection_size = floor(0.1*population_size)
max_generations = 50
probability_of_individual_mutating = 0.1
probability_of_gene_mutating = 0.25
best_possible = multiple_linear_regression(inputs, outputs)
best_individuals_stash = [create_individual(individual_size)]
initial_population = create_population(individual_size, 1000)
current_population = initial_population
termination = False
generation_count = 0
while termination is False:
current_best_individual = get_fitness(best_individuals_stash[-1], inputs)
print('Generation: ', generation_count)
best_individuals = evaluate_population(current_population)
current_population = get_new_generation(best_individuals)
termination = check_termination_condition(current_best_individual)
generation_count += 1
else:
print(get_fitness(best_individuals_stash[-1], inputs))
دیدگاهتان را بنویسید