




# Logistic Regression from scratch

# In[62]:

# In[63]:

# importing all the required libraries

import numpy as np
from matplotlib import pyplot as plt
from sklearn import datasets

def  UpperCAmelCase_							(				__UpperCAmelCase						:     Optional[int]							) ->			Tuple:
						return 1 / (1 + np.exp(-z							))

def  UpperCAmelCase_							(				__UpperCAmelCase						:     str      ,      __UpperCAmelCase						:     int							) ->			int:
						return (-y * np.log(__UpperCAmelCase							) - (1 - y) * np.log(1 - h							)).mean()

def  UpperCAmelCase_							(				__UpperCAmelCase						:     List[Any]      ,      __UpperCAmelCase						:     int      ,      __UpperCAmelCase						:     Tuple							) ->			Dict:
						SCREAMING_SNAKE_CASE_     						=      np.dot(__UpperCAmelCase      ,      __UpperCAmelCase							)
						return np.sum(y * scores - np.log(1 + np.exp(__UpperCAmelCase							)							)							)

def  UpperCAmelCase_							(				__UpperCAmelCase						:     Dict      ,      __UpperCAmelCase						:     int      ,      __UpperCAmelCase						:     List[str]      ,      __UpperCAmelCase						:     str=7_00_00							) ->			Optional[int]:
						SCREAMING_SNAKE_CASE_     						=      np.zeros(x.shape[1]							)

						for iterations in range(__UpperCAmelCase							):
												SCREAMING_SNAKE_CASE_     						=      np.dot(__UpperCAmelCase      ,      __UpperCAmelCase							)
												SCREAMING_SNAKE_CASE_     						=      sigmoid_function(__UpperCAmelCase							)
												SCREAMING_SNAKE_CASE_     						=      np.dot(x.T      ,      h - y							) / y.size
												SCREAMING_SNAKE_CASE_     						=      theta - alpha * gradient  # updating the weights
												SCREAMING_SNAKE_CASE_     						=      np.dot(__UpperCAmelCase      ,      __UpperCAmelCase							)
												SCREAMING_SNAKE_CASE_     						=      sigmoid_function(__UpperCAmelCase							)
												SCREAMING_SNAKE_CASE_     						=      cost_function(__UpperCAmelCase      ,      __UpperCAmelCase							)
												if iterations % 1_00 == 0:
																		print(f"loss: {j} \t"							)  # printing the loss after every 100 iterations
						return theta


# In[68]:

if __name__ == "__main__":
			lowerCamelCase__			:       List[str]         =							datasets.load_iris()
			lowerCamelCase__			:       Tuple         =							iris.data[:, :2]
			lowerCamelCase__			:       Any         =							(iris.target != 0) * 1

			lowerCamelCase__			:       Any         =							0.1
			lowerCamelCase__			:       Union[str, Any]         =							logistic_reg(alpha, x, y, max_iterations=70_000)
			print('theta: ', theta)  # printing the theta i.e our weights vector

			def  UpperCAmelCase_							(				__UpperCAmelCase						:     Tuple							) ->			List[str]:
									return sigmoid_function(
									    np.dot(__UpperCAmelCase      ,      __UpperCAmelCase							)							)  # predicting the value of probability from the logistic regression algorithm

			plt.figure(figsize=(10, 6))
			plt.scatter(x[y == 0][:, 0], x[y == 0][:, 1], color='b', label='0')
			plt.scatter(x[y == 1][:, 0], x[y == 1][:, 1], color='r', label='1')
			(lowerCamelCase__)			:       Optional[int]         =							(x[:, 0].min(), x[:, 0].max())
			(lowerCamelCase__)			:       Union[str, Any]         =							(x[:, 1].min(), x[:, 1].max())
			(lowerCamelCase__)			:       Optional[Any]         =							np.meshgrid(np.linspace(xa_min, xa_max), np.linspace(xa_min, xa_max))
			lowerCamelCase__			:       Dict         =							np.c_[xxa.ravel(), xxa.ravel()]
			lowerCamelCase__			:       Union[str, Any]         =							predict_prob(grid).reshape(xxa.shape)
			plt.contour(xxa, xxa, probs, [0.5], linewidths=1, colors='black')

			plt.legend()





			plt.show()





def  UpperCAmelCase_							(				__UpperCAmelCase						:     str							) ->			str:
      SCREAMING_SNAKE_CASE_     						=      ''
      for ch in key:
            if ch == " " or ch not in key_no_dups and ch.isalpha():
                  key_no_dups += ch
      return key_no_dups

def  UpperCAmelCase_							(				__UpperCAmelCase						:     str							) ->			dict[str, str]:
      SCREAMING_SNAKE_CASE_     						=      [chr(i + 65							) for i in range(26							)]
      # Remove duplicate characters from key
      SCREAMING_SNAKE_CASE_     						=      remove_duplicates(key.upper()							)
      SCREAMING_SNAKE_CASE_     						=      len(__UpperCAmelCase							)
      # First fill cipher with key characters
      SCREAMING_SNAKE_CASE_     						=      {alphabet[i]: char for i, char in enumerate(__UpperCAmelCase							)}
      # Then map remaining characters in alphabet to
      # the alphabet from the beginning
      for i in range(len(__UpperCAmelCase							)      ,      26							):
            SCREAMING_SNAKE_CASE_     						=      alphabet[i - offset]
            # Ensure we are not mapping letters to letters previously mapped
            while char in key:
                  offset -= 1
                  SCREAMING_SNAKE_CASE_     						=      alphabet[i - offset]
            SCREAMING_SNAKE_CASE_     						=      char
      return cipher_alphabet

def  UpperCAmelCase_							(				__UpperCAmelCase						:     str      ,      __UpperCAmelCase						:     dict[str, str]							) ->			str:
      return "".join(cipher_map.get(__UpperCAmelCase      ,      __UpperCAmelCase							) for ch in message.upper()							)

def  UpperCAmelCase_							(				__UpperCAmelCase						:     str      ,      __UpperCAmelCase						:     dict[str, str]							) ->			str:
      SCREAMING_SNAKE_CASE_     						=      {v: k for k, v in cipher_map.items()}
      return "".join(rev_cipher_map.get(__UpperCAmelCase      ,      __UpperCAmelCase							) for ch in message.upper()							)

def  UpperCAmelCase_							(				) ->			None:
      SCREAMING_SNAKE_CASE_     						=      input('Enter message to encode or decode: '							).strip()
      SCREAMING_SNAKE_CASE_     						=      input('Enter keyword: '							).strip()
      SCREAMING_SNAKE_CASE_     						=      input('Encipher or decipher? E/D:'							).strip()[0].lower()
      try:
            SCREAMING_SNAKE_CASE_     						=      {'e': encipher, 'd': decipher}[option]
      except KeyError:
            raise KeyError('invalid input option'							)
      SCREAMING_SNAKE_CASE_     						=      create_cipher_map(__UpperCAmelCase							)
      print(func(__UpperCAmelCase      ,      __UpperCAmelCase							)							)


if __name__ == "__main__":
   import doctest

   doctest.testmod()
   main()