Qiskit has a function which initializes a circuit to a certain given state:
https://qiskit.org/documentation/stubs/qiskit.extensions.Initialize.html
The paper that they use to implement the code apparently is:
https://arxiv.org/abs/quant-ph/0406176v5
A small example of code to implement the function is:
from qiskit.circuit import QuantumCircuit
from qiskit.circuit import QuantumRegister
nbqbits = 2 # Number of qubits
qr = QuantumRegister(nbqbits)
qc = QuantumCircuit(qr)
##In psi_0 you define the amplitudes of the state. These amplitudes are the square root
## of the probabilites you want to get for each state.
## Each state of the computational basis binary(i) get the amplitude psi_0[i], i.e:
## The state |00> get the amplitude psi_0[0]
## The state |01> get the amplitude psi_0[1]
## and so on.
psi_0 = [1, 2, 3, 4] # This state is not yet normalized
psi_0 = psi_0/np.linalg.norm(psi_0) # Normalization of the state
qc.initialize(psi_0) # Initialize function. Make sure that the vector you enter has 2**nbqbits entries.
qc.draw(output='mpl')
You should get something like:

If you decompose the circuit, you can get more information about what gates are inside:
d_c = qc.decompose().decompose().decompose().decompose()
d_c.draw(output='mpl')
and you would get:
